By Harry Roberts
Harry Roberts is an independent consultant web performance engineer. He helps companies of all shapes and sizes find and fix site speed issues.
Written by Harry Roberts on CSS Wizardry.
Bar charts in CSS are neither very new, or very difficult. Using some pretty basic styling you can force lists etc into resembling graphs and charts fairly easily. Such charts, in their most basic form, work perfectly well in displaying and presenting the data they represent. However, using some rich CSS3 and progressive enhancement, you can really start pushing the display and presentation of these normally boring documents to the next level. They are also an ideal way in which to demonstrate the power and ability of progressive enhancement.
Look at the site in IE8, then Firefox, then Safari/Chrome. Keep refreshing.
I have created a demo page which simply represents three items of data expressed as percentages. It is not the data itself or the numbers we are concerned with here–it is the proof of concept. The fact that this can be done on my made up data shows that you can do it too, on real life information.
At Venturelab, we decided to use progressive enhancement as a matter of course. CSS3 and designing in the browser all the way!
Progressive enhancement is, in my opinion, one of the most exciting schools of thought web development has seen in years (though I have only been in the web for three…). It is the idea whereby any non-essential features (i.e. anything whose absence will have no adverse effect on the usability or accessibility of a website) are added to the website in a progressive manner–often through CSS3.
The benchmark example is rounded corners; to apply these through old means, for example with images, would have taken a developer a substantial amount of time–time the client is paying for. It seems silly now to think that way-back-when, putting rounded corners on a div
might have taken upward of 30 minutes, when we can apply it in about 5 seconds using -moz-border-radius:5px;
.
It really is a no brainer–anyone visiting the site in a browser with no CSS3 support will see square corners. Does this matter? Of course it doesn’t. No one visits a site to look solely at the design–they visit for content. Does it matter to them what shape the corners of your RSS button are? No again. Progressive enhancement saves you time, and your client money.
Graceful degradation = building for the best and getting worse; progressive enhancement = building to cater the worst and getting better…
The line between progressive enhancement and graceful degradation is fine but significant. Graceful degradation is the idea that you’d build a site for, say, Firefox, then selectively break and downgrade it in the likes of IE(6). Progressive enhancement takes a much more positive attitude in that you build for IE(6) and then selectively upgrade it in browsers like Firefox and Safari. It’s no longer starting great and getting worse, it’s now starting great and getting better.
N.B. Only tested in IE8 as this is not a final solution, rather a proof-of-concept.
Internet Explorer(8)’s take on my bar charts is as you’d expect from any browser, it renders it perfectly well, providing clear, accessible content, with a flawless UX and perfectly usable. This is not bad! We don’t need to downgrade anything, this is our starting point. It looks good and it functions perfectly. If you did as above and visited in IE8 first, you wouldn’t know that there were round corners missing–because that doesn’t matter.
Next up is Firefox, where we add some round corners to the blue bars, and also a very subtle drop shadow (text-shadow:;
) on the text. This is no more usable than before, the content is no more accessible than in IE, but it does look a tad nicer.
It is in Webkit based browsers such as Safari and Chrome that the real magic happens. Webkit’s proprietary CSS is above and beyond that of any other rendering engine…
What if I couldn’t be bothered opening Photoshop to make a subtle gradient .gif
for the bars? No worries, use Webkit’s gradient CSS. A little reflection might look nice on the bars too, but I don’t fancy any superfluous markup or .png
s to fiddle with. Ah great, Webkit has a bit of reflection CSS too.
However, for the real show-piece, the Webkit animation. I’m not using any Javascript libraries anywhere else in the page so I don’t fancy pulling a whole one in for something that won’t really be missed if it’s not there. I hear Webkit has animations… magic!
Now that’s the theory covered, let’s look at what does all this stuff… Please note, I have used some PHP to randomise the values used by the bars of the chart. As a result, some CSS appears in the source code of the PHP file, and the rest in the page’s CSS file. The code shown in the examples below is condensed into one large chunk.
The markup simply comprises of one uncluttered dl
. The reasoning behind a definition list is that each item is a title, followed by some information about that title. Not only is this semantically correct, it’s a nice set of elements to be working with to achieve the layout we’ve got.
<code><dl id="chart">
<dt>Sales increase this week</dt>
<dd><span id="data-one">47%</span></dd>
<dt>Revenue increase this week</dt>
<dd><span id="data-two">59%</span></dd>
<dt>Profit increase this week</dt>
<dd><span id="data-three">26%</span></dd>
</dl></code>
That’s all there is to it.
<code><span class="code-comment">/*------------------------------------*\
CHART
\*------------------------------------*/</span>
#chart{
width:520px;
}
#chart dt{
width:160px;
float:left;
margin:0 20px 5px 0;
padding:2px 0;
display:inline;
font-weight:bold;
text-align:right;
}
#chart dd{
width:339px;
border-right:1px solid #ddd;
float:left;
margin-bottom:5px;
display:inline;
}
#chart dd span{
color:#fff;
background:#09f;
text-align:center;
padding:2px 0;
display:block;
text-shadow:1px 1px 1px rgba(0,0,0,0.2);
-moz-border-radius:2px;
-webkit-border-radius:2px;
border-radius:2px;
background:-webkit-gradient(linear, left top, ->
left bottom, from(#09f), to(#077fd0));
-webkit-box-reflect:below 0 ->
-webkit-gradient(linear, left top, ->
left bottom, from(rgba(0,0,0,0)), to(rgba(0,0,0,0.25)));
}
#data-one{
width:47%;
}
#data-two{
width:59%;
}
#data-three{
width:26%;
}
#data-one{
-webkit-animation-name:bar-one; <span class="code-comment">/* Give the bar an animation with a
unique name */</span>
}
#data-two{
-webkit-animation-name:bar-two; <span class="code-comment">/* Give the bar an animation with a
unique name */</span>
}
#data-three{
-webkit-animation-name:bar-three; <span class="code-comment">/* Give the bar an animation with a
unique name */</span>
}
#data-one,#data-two,#data-three{ <span class="code-comment">/* Define animation styles for all three
bars at once */</span>
-webkit-animation-duration:0.5s; <span class="code-comment">/* Animation duration in seconds */</span>
-webkit-animation-iteration-count:1; <span class="code-comment">/* Amount of times to loop */</span>
-webkit-animation-timing-function:ease-out; <span class="code-comment">/* Ease in, out etc. */</span>
}
@-webkit-keyframes bar-one{
0%{ <span class="code-comment">/* Define bar-one styles at 0% (0 seconds) */</span>
width:0%;
}
100%{ <span class="code-comment">/* Define bar-one styles at 100% (0.5 seconds) */</span>
width:47%;
}
}
@-webkit-keyframes bar-two{
0%{ <span class="code-comment">/* Define bar-two styles at 0% (0 seconds) */</span>
width:0%;
}
100%{ <span class="code-comment">/* Define bar-two styles at 100% (0.5 seconds) */</span>
width:59%;
}
}
@-webkit-keyframes bar-three{
0%{ <span class="code-comment">/* Define bar-three styles at 0% (0 seconds) */</span>
width:0%;
}
100%{ <span class="code-comment">/* Define bar-three styles at 100% (0.5 seconds) */</span>
width:26%;
}
}</code>
There may well be some bits in there that you’re not familiar with, particularly CSS animations. Basically, to animate an element you need to do a few things:
<code>#data-one{
-webkit-animation-name:bar-one;
}</code>
<code>#data-one,#data-two,#data-three{
-webkit-animation-duration:0.5s;
-webkit-animation-iteration-count:1;
-webkit-animation-timing-function:ease-out;
}</code>
<code>@-webkit-keyframes bar-one{
0%{
width:0%;
}
100%{
width:47%;
}
}</code>
With regards the Webkit reflections, it may be a better idea to consult the Surfin’ Safari page on that, as anything I’d say would most likely be a poorly pulled off rehash.
So there you have it, a real life, justifiable and wholly appropriate application of CSS3 and progressive enhancement coupled with data visualisation. Don’t be held back by the limitations of older browsers–relish in the opportunities new ones bring.
And as a final bonus, @VIPickering requested this (view in Safari/Chrome)… enjoy.
Harry Roberts is an independent consultant web performance engineer. He helps companies of all shapes and sizes find and fix site speed issues.
Hi there, I’m Harry Roberts. I am an award-winning Consultant Web Performance Engineer, designer, developer, writer, and speaker from the UK. I write, Tweet, speak, and share code about measuring and improving site-speed. You should hire me.
You can now find me on Mastodon.
I am available for hire to consult, advise, and develop with passionate product teams across the globe.
I specialise in large, product-based projects where performance, scalability, and maintainability are paramount.