Skip directly to content

CSS

Styling Raphael.js Elements With CSS

on Mon, 04/16/2012 - 14:36

Recently finished up a project in which one of the major requirements was that everything be re-skinnable. This meant that every interface element needed to be styled through the style sheet. Swap out a single file to completely change the look of the site.

In theory, this shouldn't be a problem; that is the raison d'etre for Cascading Style Sheets. Where things got  little complicated, however, was in the many, many charts created using Raphael.js. Even the colors used therein needed to be accessible from the .css files.

Raphael produces SVG elements, which are added dynamically to the DOM. I found that the easiest way to style them was to, at the point of creating the individual elements, use Javascript (jQuery, in this case) to add class names. And that simply, everything works! See an example here. Reload the page to re-render the elements. Code follows:

<!doctype html>
<html>
	<head>
		<title>Styling Raphael.js Elements with CSS</title>
		<script type="text/javascript" src="jquery-1.7.1.min_.js"></script>
		<script type="text/javascript" src="raphael-min.js"></script>
		<script type="text/javascript">
			var r1,r2,i
			$(document).ready(function(){
				r1 = new Raphael('raph1',320,320);
				for(i=0;i<50;i++) {
					var s1 = Math.round(Math.random()*300)+10;
					var s2 = Math.round(Math.random()*300)+10;
					var e1 = Math.round(Math.random()*300)+10;
					var e2 = Math.round(Math.random()*300)+10;
					var s = Math.round(Math.random()*5);
					var c = Math.round(Math.random()*5);
					var p = "M"+s1+","+s2+"L"+e1+","+e2;
					var out = r1.path(p).attr({"stroke-width":s});
					$(out.node).attr('class','c'+c);
				}
				r2 = new Raphael('raph2',320,320);
				for(i=0;i<50;i++) {
					var x = Math.round(Math.random()*320);
					var y = Math.round(Math.random()*320);
					var r = Math.round(Math.random()*32);
					var s = Math.round(Math.random()*5);
					var c = Math.round(Math.random()*5);
					var f = Math.round(Math.random()*5);
					var out = r2.circle(x,y,r).attr({"stroke-width":s});
					$(out.node).attr('class','c'+c + ' f'+f);
				}
			});
		</script>
		<style type="text/css">
			* {margin:0;padding:0;}
			h4 {margin:20px 20px 0 20px;}
			.demo {width:320px;height:320px;margin:5px 20px 20px 20px;border:1px solid #cccccc;}
			.c0 {stroke:#ff0000;}
			.c1 {stroke:#00ff00;}
			.c2 {stroke:#0000ff;}
			.c3 {stroke:#ffff00;}
			.c4 {stroke:#ff00ff;}
			.c5 {stroke:#00ffff;}
			
			.f0 {fill:#222222;}
			.f1 {fill:#444444;}
			.f2 {fill:#666666;}
			.f3 {fill:#888888;}
			.f4 {fill:#aaaaaa;}
			.f5 {fill:#cccccc;}
		</style>
	</head>
	<body>
		<h4>Styling stroke color</h4>
		<div class="demo" id="raph1"></div>
		<h4>Styling stroke color and fill color</h4>
		<div class="demo" id="raph2"></div>
	</body>
</html>

and so forth. CSS classes and IDs work the same for SVG elements as they do for HTML elements. The big difference is that SVG styles which mimic HTML styles use different key words. Where you would set a background color on a HTML element using background-color:#cccccc, in SVG you would use fill:#cccccc. Stroke is the SVG version of border.

Here is a short list of helpful links for styling SVG with CSS:

SVG and CSS

Style reference at Mozilla Developer Network

Circular HTML Elements Using CSS3 Border Radius

on Thu, 10/13/2011 - 23:03

If you are using a "modern" browser, you should see a box full of circles.

 

abcde fghij klmno pqrst uvwxy z

If not, you need to upgrade your browser.

The circles were created using the new CSS3 border-radius property. The markup I used looks something like this:

<div id="post-20111013-a">
<span>a</span><span>b</span><span>c</span><span>d</span><span>e</span>
<span>f</span><span>g</span><span>h</span><span>i</span><span>j</span>
<span>k</span><span>l</span><span>m</span><span>n</span><span>o</span>
<span>p</span><span>q</span><span>r</span><span>s</span><span>t</span>
<span>u</span><span>v</span><span>w</span><span>x</span><span>y</span>
<span class="s2">z</span>
</div>
#post-20111013-a {width:640px;height:480px;outline:1px solid #999;background:#ffffff;}
#post-20111013-a span {
	float:left;
	width:50px;
	height:50px;
	margin:14px;
	border:1px solid red;
	background:#999999;
	-webkit-border-radius: 27px;
	-moz-border-radius: 27px;
	border-radius: 27px;
	text-align:center;
	line-height:50px;
}
#post-20111013-a span.s2 {
	float:none;
	clear:both;
	display:block;
	margin:20px auto;
	width:100px;
	height:100px;
	line-height:100px;
	-webkit-border-radius: 54px;
	-moz-border-radius: 54px;
	border-radius: 54px;
}
#post-20111013-a span:hover {
	-webkit-box-shadow: 5px 5px 5px 0px rgba(0, 0, 0, .5);
	-moz-box-shadow: 5px 5px 5px 0px rgba(0, 0, 0, .5);
	box-shadow: 5px 5px 5px 0px rgba(0, 0, 0, .5);
}
#post-20111013-a span.s2:hover {
-webkit-box-shadow: 0px 0px 20px 20px rgba(255, 0, 0, .5);
	-moz-box-shadow: 0px 0px 20px 20px rgba(255, 0, 0, .5);
	box-shadow: 0px 0px 20px 20px rgba(255, 0, 0, .5);
}

The first block is the HTML which makes up the above demo, and the second is the style sheet. Pretty self-explanatory. I set the border radius to slightly more than half of the diameter of the circle (width/height of the element). Putting the border radius at exactly half of the diameter renders as a very slightly squarish circle. You can play around with border-radius on this page at the w3schools. You can read more about the browser compatibility and best practices at The Art of the Web.

Unfortunately the hit area for each element is still a rectangle large enough to contain the circle, so in that sense it is not much of an improvement over using a background image. Still, it is a huge step in the right direction.