For a project I am working on right now I needed to have really fast bar charts that don't need any plugins or rely heavily on JavaScript. This is why I've put together some bar charts in pure CSS. Try this - move your mouse over the bars:

  • 400
  • 20
  • 30
  • 233
  • 312
  • 78
  • 20
  • 67

And here's how this works:

Starting with a simple nested list:

<ul>
     <li>400</li>
     <li>20</li>
     <li>30</li>
     <li>233</li>
     <li>312</li>
     <li>78</li>
     <li>20</li>
     <li>67</li>
   </ul>

This renders normally something like this:

  • 400
  • 20
  • 30
  • 233
  • 312
  • 78
  • 20
  • 67

Adding a bit more CSS, we can turn them into bars:

ul{
  margin:0;
  padding:0;
  background:#eee;
  border:1px solid #999;
  height:100px;
  width:600px;
  list-style:none;
  overflow:hidden;
}
li{
  height:100px;
  list-style:none;
  margin:0;
  padding:0;
  float:left;
  width:75px;
  background:#369;
}
  • 400
  • 20
  • 30
  • 233
  • 312
  • 78
  • 20
  • 67

We use overflow on the UL to contain the floated LIs. The display of the values is nice in the LI but the problem is that when the bar is not big enough, we wouldn't be able to read them. We could use text-indent to hide the texts, but let's add a span instead to have a better handle:

<ul>
  <li><span>400</span></li>
  <li><span>20</span></li>
  <li><span>30</span></li>
  <li><span>233</span></li>
  <li><span>312</span></li>
  <li><span>78</span></li>
  <li><span>20</span></li>
  <li><span>67</span></li>
</ul>

Adding the right CSS, we can have a hover bar with the text displayed on the top left:

ul{
  margin:0;
  padding:0;
  background:#eee;
  border:1px solid #999;
  overflow:hidden;
  height:100px;
  width:600px;
  list-style:none;
  position:relative;
}
li{
  height:100px;
  list-style:none;
  margin:0;
  padding:0;
  float:left;
  width:75px;
  background:#369;
}
li span{
  position:absolute;
  top:1em;
  left:-9999px;
}
li:hover{
  background:#69c;
}
li:hover span{
  left:1em;
}

Move your mouse over the bar to see it in action:

  • 400
  • 20
  • 30
  • 233
  • 312
  • 78
  • 20
  • 67

Now how do we get this to be bar charts? Using a border on the top that is the same background colour than the UL and some maths.

<ul>
  <li style="border-top-width:0px">
    <span>400</span>
  </li>
  <li style="border-top-width:95px">
    <span>20</span>
  </li>
  <li style="border-top-width:92px">
    <span>30</span>
  </li>
  <li style="border-top-width:41px">
    <span>233</span>
  </li>
  <li style="border-top-width:22px">
    <span>312</span>
  </li>
  <li style="border-top-width:80px">
    <span>78</span>
  </li>
  <li style="border-top-width:95px">
    <span>20</span>
  </li>
  <li style="border-top-width:83px">
    <span>67</span>
  </li>
</ul>

The only change in the CSS is to add a border:

ul{
  margin:0;
  padding:0;
  background:#eee;
  border:1px solid #999;
  overflow:hidden;
  height:100px;
  width:600px;
  list-style:none;
  position:relative;
}
li{
  height:100px;
  list-style:none;
  margin:0;
  padding:0;
  float:left;
  width:75px;
  background:#369;
  border-top:1px solid #eee
}
li span{
  position:absolute;
  top:1em;
  left:-9999px;
}
li:hover{
  background:#69c;
}
li:hover span{
  left:1em;
}

Move your mouse over the following example to see the effect:

  • 400
  • 20
  • 30
  • 233
  • 312
  • 78
  • 20
  • 67

Add a bit more fancy CSS and you get this:

  • 400
  • 20
  • 30
  • 233
  • 312
  • 78
  • 20
  • 67

Automating the process

Doing this by hand is annoying, and computers love to do calculations for us. This is why I packaged the trick up into a PHP script. The above chart was done with the following code:

<?php 
  $values = '400,20,30,233,312,78,20,67';
  $height = 100;
  $width = 600;
  $bargap = 0;
  include('csscharts.php');
?>

This does not only calculate the bar height but also the width. You can also apply a gap in between the bars - see the demo page for a lot of examples.

Using as a web service

You can also use this script as a web service by giving the parameters over the URI:

http://icant.co.uk/csscharts/csscharts.php?values=400,20,30,233,312,78,20,67&height=100&width=600&bargap=0

The returned HTML is a UL with the right inline measures and a class called "barchart". Go nuts styling it.

If you add a format parameter with the value json you get it back as a callback to the function csscharts().

http://icant.co.uk/csscharts/csscharts.php?values=400,20,30,233,312,78,20,67&format=json

csscharts(
  {
    chart:"<ul class=\"barchart\" [… the rest of the html …]</ul>"
  }
)

You can use that to create charts dynamically with JavaScript. Try it out by submitting the form:

HTML:
  
<form action="index.php" method="get" id="f">
 <div>
   <label for="values">Values</label>
   <input name="values" id="values"
          type="text" 
          value="10,230,80,40,20">
   </div>
 <div>
   <label for="bargap">Bar gap</label>
   <input name="bargap" id="bargap"
          type="text" value="0">
 </div>
 <div>
   <label for="width">Chart width</label>
   <input name="width" id="width" 
          type="text" value="400">
 </div>
 <div>
   <label for="width">Chart height</label>
   <input name="height" id="height"
          type="text" value="200">
 </div>
 <div>
   <input type="submit" 
          value="show graph" id="s">
  </div>
</form>
JavaScript:

(function(){
var $ = function(id){
  return document.getElementById(id);
};
var d = document;
var f = $('f');
f.onsubmit = function(){
  var button = $('s');
  button.setAttribute('value','loading...');
  var url = 'csscharts.php?format=json';
  var fields = ['height','width','bargap',
                'values'];
  for(var i=0;i<fields.length;i++){
    var val = $(fields[i]).value;
    url += '&' + fields[i] + '=' + val;
  }
  var s = document.createElement('script');
  s.setAttribute('src',url);
  s.id = 'leech';
  var head = d.getElementsByTagName('head')[0];
  head.appendChild(s);
  return false;
}
})();
function csscharts(o){
  var c = document.getElementById('out');
  var s = document.getElementById('leech');
  s.parentNode.removeChild(s);
  c.innerHTML = o.chart + c.innerHTML;
  var b = document.getElementById('s');
  b.setAttribute('value','show graph');
}
  
       

Download

You can download the demos and csscharts.php from the CSScharts GitHub repository.