posted on:February 11, 2009

Pure Css Line Graph

I often think about ways to visualize data using pure css. A while ago I wrote an article about pure css bar graphs, but what puzzled me lately was a solution for doing line graphs using nothing but css.
Many will not see much sense in this technique, specially when we have so much JavaScript (or even Flash) based line graph scripts.

My intention was not only to enable data visualization to people that don’t feel comfortable with using various scripting languages but also to demonstrate the power of css and present a way of using css a bit differently. If you are not a fan of line graphs and data visualization in general, you may still read this article and think of it as css experiment and perhaps learn a thing or two about css sprites and positioning.

pure css line graph

Take a look at the demo
| Download pure css line graph

So, the line graphs. What are they good for? I will mention just one reason, and leave other advantages or downsides for a debate: users scan your page, they don’t read every word and number you write. Line graphs will deliver information much faster then a table filled with numbers.

How does this thing work?

This technique takes structured html, replace text with images and by using css sprites and absolute positioning it creates a simulation of a line graph. As in my pure css bar graph example, I am using definition list element (DL). DL element is styled to represents the coordinate system where we place items. For that reason, empty DL element must look something like this:

dl background

The dimensions used in the background graphic define the dimensions we’re using for child elements in order for everything to fit well. In this case, each item will represent one day. For items we are using DD elements with nested spans. We are formatting and placing the DL’s so they form linear bars across the chart.

dd elements

The styling of nested spans are what makes this css line graph possible.

The Graph Principle

The concept may seem a bit advanced but if you look carefully into it you’ll see that the logic is quite simple. In my example item’s (DD’s) dimensions are 33px in width and 330px in height. Each one of those items represent one "line movement" from one point to the other. We’re using one image, css sprite, that has all possible options displayed graphically. As you can see on the image, there are lines that go up (rising values) and lines that go down (falling values). Setting the nested SPAN’s background-position property to certain values we are choosing one of the "line" options.

dd background positioning

But that is not all. We also have to set the "starting position" for each item as the lines always start at different values. That is done by setting top value for each SPAN

dd top offset

For this reason, each SPAN has 2 (actually some of them have 3 – read below) class names attached: one that defines the SPAN’s "starting point" (SPAN’s top value) and other that represent the rising or falling "line move" (SPAN’s background position value).
Starting point is based on previous value. You have to continue with next item where the previous item "stopped".


If you look at the css file I created 4 groups of class names: 2 for setting starting position and 2 for defining the "move".
I divided starting position class name groups based on the situation where we are increasing values (using line-up, the upper part of the image) or decreasing values (lower part of the image).
I named those class names .pi1 or .pd1 ("p"osition "i"ncreasing 1) or ("p"osition "d"ecreasing 1) By looking at the css file you’ll notice that .pi group has negative top values which shits sprite image up while .pd group has positive top values (shifts image down).

Actual line movements are defined with class names like .i1 or .d1 i.e. this class name .i24 increases the value by 24 points.

Choosing a proper position (".p" class) is fairly easy: you have to take a look at previous item which can be something like:

<dd><span class="pi1 i10"><em>33</em></span></dd>

We have pi1 and i10. It means that we have item starting at point 1 and is increased by 10 points. That makes point 11 our new starting point. If our next move is increase we are choosing .pi11 but if we’re decreasing we choose .pd11!

If this sound to complex (or if I presented it poorly) just remember that when choosing both class name you have to be careful that you don’t mix i’s and d’s

This is good:

<dd><span class="pi1 i10"><em>33</em></span></dd>

and this isn’t

<dd><span class="pi1 d10"><em>33</em></span></dd>

Now, let me explain what’s with the EM element. Items are placed next to each other without overlapping so the line connections are not smooth. I am using EMs to place dots over these connecting points to cover them. EMs are absolutely positioned to cover the PREVIOUS line connection area. There is one default css definition for EMs although the decreasing items need additional class name .d – that’s why I mentioned that some of the SPANS has 3 class names. The decreasing item is marked up like this:

<dd><span class="pd10 d d1"><em>46</em></span></dd>

Please note that class names are written in "points" or "steps" not the actual values. In my case each "point" represents 3,3%

As mentioned, I am not trying to replace advanced JS or flash techniques with this. I am offering an alternative way to visualize data and perhaps different view of CSS usage. This method has it’s limitations, but it’s pure CSS!

Enjoyed the article?

Then don't miss our next one! Subscribe to our RSS feed or share it with your friends.

DeliciousStumbleUpon RedditSubscribe

Comments (60 Comments)

  1. Bennobo
    February 11, 2009

    I really like your solution. Especially the unusual way of using a sprite!
  2. Cerebral
    February 11, 2009

    Congrats, really well thought.
  3. webdawson
    February 11, 2009

    awesome, love it :)
  4. w0w
    February 11, 2009

    did something like that in my previous freelance project. the good thing about css graph is that it's easy to generate from the back end
  5. vladocar
    February 11, 2009

    Lovely experiment!
  6. Dado
    February 11, 2009

    Very nice technique. :)
  7. Ollie
    February 11, 2009

    This is awesome, real science & art. I'm saving this for later. Thanks!
  8. Pliggs
    February 11, 2009

    Wow, that's a great way to accomplish it. Thanks for the share.
  9. Umut Muhaddisoglu
    February 11, 2009

    I think this is a genious work. I'm really amazed in every step while reading it.
  10. Aiya101
    February 11, 2009

    How is this pure CSS when you're using a giant image for the lines?
  11. Chris M
    February 11, 2009

    I've always wondered how this was done. Thank you for sharing your solution with all of us.
  12. Jonathan Snook
    February 11, 2009

    @Aiya101, you're absolutely right! He used an image! and HTML, too! This is false advertising!
  13. Soh
    February 11, 2009

    Alen, you are one clever man... Very nice.
  14. James Howard
    February 11, 2009

    "which shits sprite image up" That'll teach them! :-)
  15. WebmasterNeal
    February 11, 2009

    Impressive, web designers have been toiling over how to do this for a long time and your very strange css-sprite appears to be the solution. Is there a mathimatical formula one could use to position/add margin to each of the elements to make this more streamlined? I.e could we integrate some JS into this that would contain an array of value that then could do all the positioning for us. I'd also like to see something integrated into this that stylizes the x & y axis. and the zebra stripes.
  16. cssProdigy
    February 11, 2009

    Is there anything CSS can't do?
  17. cssglobe
    February 11, 2009

    Thanks guys for kind words!
  18. cssglobe
    February 11, 2009

    @WebmasterNeal: I've tried to explain the simple math behind this. Not sure if I will do a better job now :) To get a "position" class name you have to take previous element's class names as a reference. If the class names previous element is using are "pi12 i4" that gives you 12+4=16! So the calculated "position" class name is .pi16 if you're increasing or .pd16 if decreasing.
  19. cssglobe
    February 11, 2009

    @snook: sorry to disappoint everyone but I also used words and numbers :)
  20. daniel
    February 11, 2009

    Very very cool, but something's off in ie6. Looks great in FF!!
  21. cssglobe
    February 11, 2009

    @daniel: I used PNGs
  22. Dean
    February 11, 2009

    Very nice. Clever. But wouldn't it be more semantically correct to have the underlying code as a table of data rows/columns than as a definition list? I wonder how much that would complicate things?
  23. w0w
    February 12, 2009

    @Dean: Unsure? Try it
  24. inner thoughts
    February 12, 2009

    "demonstrate the power of css and present a way of using css a bit differently" I think that tricks/hacks like this only show how terrible an HTML is and that even CSS cannot remedy the fundamental flaw of the whole HTML concept! Even (W3C) standards cannot fix it! I see people everywhere thinkering hacks, tricks and other clever ways to get something so obvious, like in this example - simple data visualisation, in HTML. If only all that energy and "brain power" is used to design and develop a completely new replacement for HTML (not based on HTML/XML and other similar crap!) - where all the mistakes in design from HTML would be gone! Just my .02$
  25. cssglobe
    February 12, 2009

    @inner thoughts: please write a blog post where you propose an alternative. I would gladly read it and publish the link here.
  26. benburleson
    February 12, 2009

    @inner thoughts - maybe you should keep those thoughts inner until, as @cssglobe mentioned, you can provide an alternative. @cssglobe - I admire thinking outside the box, especially when it comes to using css sprites. But I really think this is the wrong tool for the job. Creating the data HTML is far too complicated. You could use js to simplify the creation of the data HTML. But then if you're going to use js, why not use js to do the graphing? Check out my css sprite project hosted at google code: I think it has some potential, and it would be nice to have some others with experience in the subject take a look at it. (And hopefully contribute!)
  27. Timothy
    February 12, 2009

    Wow. Sick!
  28. Creamy CSS
    February 12, 2009

    Unbelievable, never thought it can be done such way! Great CSS mind! ;)
  29. Eli
    February 12, 2009

    Hey, great article. I've been researching a lot of graphing techniques of late. Small correction: "This method has it's limitations, but it's pure CSS!" "It's" means "it is". It should be "This method has its limitations, but it's pure CSS!"
  30. Márton Sári
    February 12, 2009

    I wouldn't say it's pure css as it uses a sprite for pre-made lines, hence the graph will "snap to grid", cannot be used for a precise graph. And it's a serious limitation. I would say it's a pure misleading title. It's a half-css method. CSS sprites have their own areas to be used in, this is definitely not in that.
  31. cssglobe
    February 12, 2009

    @Márton Sári: You are a second commenter claiming that using images with css can't be called a css solution. Although I understand the point you're trying to make, I believe that when developing a "css solution" you are free to use all available css properties. Therefore manipulations with background images could be considered a css solution. In a broader sense, when saying that something is "Pure CSS" the fact that I'm trying to emphasize is that i haven't used any scripting languages. That was actually my main reason for calling this pure css solution.
  32. Athos
    February 12, 2009

    Here's an attempt to draw line graphs with CSS without utilizing any images or other trickery. It works in most of the browsers. (It's not a general solution to draw lines, and it seems to be impossible to draw multiple lines on the same graph with my code.)
  33. Simon Sigurdhsson
    February 12, 2009

    I said the same thing about the bar graph, but I'll say it again; graph data is better represented by an image than by (albeit cleverly styled) dl elements. It's cool but redundant and unsemantic...
  34. Márton Sári
    February 13, 2009

    @cssglobe: Yea, I see your point, it's pure CSS in the sense you don't make use of any other technology, but not in the sense as in, e.g., CSS Data Charts. In Data Charts you make graphic scaling by a CSS value, that's not the case here, here you use a CSS value for picking an image from a pre-made selection. It's a significant difference. Actually it doesn't even have a real relevance of the images being in a sprite, it could be all in seperate files. The relevance of using CSS sprites here is just the same as in using sprites generally: performance. That's why it's misleading. The sprite idea doesn't add anything to the concept. So the question is, that without sprites (separate image files) would you still call it a "pure CSS solution", and not rather a "pure HTML solution"?
  35. Márton Sári
    February 13, 2009

    @Athos: Debate over, that's what i call a pure css solution :)
  36. inner thoughts
    February 13, 2009

    Athos said "Here's an attempt to draw line graphs with CSS without utilizing any images or other trickery." Wow! Isn't using borders and overlapping elements to get thinner lines actually, what you call, "other trickery"? :) At least cssglobe's solution is nice looking and usable. That can't be said for your "trickery"!
  37. inner thoughts
    February 13, 2009

    @cssglobe: I don't write blogs. If I change my mind and write something like that I'll let you know. :) @benburleson: Why? People should exchange thoughts and discuss them. There is nothing wrong wanting new and better things to happen. Also, you imply that I have no right to say that something is broken/wrong/bad unless I have a solution or alternative? Interesting. Have you ever said for anything (product, tv show, movie) "that is bad" and all that without an alternative? I still stand at my view that HTML (with related stuff) is bad, very very broken and it should be abandoned and replaced! Today (X)HTML/CSS/JS/.. is totally FUBAR!
  38. Márton Sári
    February 13, 2009

    @inner thoughts: „At least cssglobe's solution is nice looking and usable.” It depends on what you wanna do, and what you mean by nice and usable. The border-trick has its own technological beauty (which I expect from a title like "pure CSS solution"), you can scale the graph in both dimensions, you can scale the distance between two spots, you can make precise graphs, you can control the color, and probably you can make it better looking that it is now on Athos' site (e.g. you can put png dot images at the breaking points hiding that glitch). And is probably standard-proof. Unfortunately it's not anti-aliased in IE and Opera.
  39. Márton Sári
    February 13, 2009

    @inner thoughts: criticizing a tv show is not the same as critizing a technology. Although in both cases you have the alternatives: not using/watching it, still, blaming a technology without any thoughts of alternatives is just boring, and is pure a sign of that you're not on the right carreer.
  40. Exdizajn
    February 13, 2009

  41. inner thoughts
    February 13, 2009

    @Marton Sari: But it's still a hack! Also what does it mean that it is "probably standard-proof"? Using divs in such way maybe doesn't break any formal validation, but it's way off "standards". HTML could hardly be called an technology. Take SGML, cripple it, give it a new name and that's a technology? With all due respect to Mr. Berners-Lee, HTML was good way back then and it was fun, but now it's just pain in the ass. That's why we need something new and hopefully better with full and native support (among other things) for vector graphics (if somebody wants to mention SVG just don't! ;), audio, video, unified server and client side programming, real bidirectional persistent communication channels, real separation of content and presentation, better indexing and data knowledge and not to mention pixel perfect rendering. There is much more, but this is just place for comments so I'll stop. My apology to cssglobe for all disturbance, won't do it anymore. :)
  42. Athos
    February 13, 2009

    @inner thoughts: my eyes are working well, I can see that my solution is very poor, but it's a pure CSS solution. It's just for fun, not to be used in real-world applications. When I write trickery, I mean cheating (using other than CSS or HTML). You say: "we need something new and hopefully better with full and native support (among other things) for vector graphics (if somebody wants to mention SVG just don't! ;), audio, video, unified server and client side programming, real bidirectional persistent communication channels, real separation of content and presentation, better indexing and data knowledge and not to mention pixel perfect rendering." I don't think this will be reality in less than 10 years...
  43. Márton Sári
    February 14, 2009

    @inner thoughts: by standard proof i mean this behaviour could be read from the css spec. Maybe i'm wrong. But maybe it's not an accident it's working in all browsers. So you have problems with only HTML? SGML is OK? XHTML is OK? What about HTML 5? You said: "HTML with related stuff". So you're blaming the whole technology. Then what's the point in questioning a term i'm using obviously to refer to that whatever technology you're speaking about, and naming it by it's probably strongest meme as an adjunct (HTML). Actually i'm getting lost what precisely do you have problems with. Maybe it's the whole world. Or just the internet. Maybe you should go cutting trees. You still haven't given a piece of thought of alternatives. Why one shouldn't mention SVG??? Audio, video -- what's with that??? You can make it on any level (with version 5 even on HTML) with any tool you want. "unified server and client side programming" WTF???, you don't like free market and competition, do you? You're pushing the same bullshit as people who are crying for a 'one and only' browser engine, so they don't have to bother with compatibility issues. Poor guys, don't notice that behind your absurd ideas it's only the simple fact is hiding that you feel really uncomfortable with you job... Why wouldn't you wish then a one and only OS, a one and only car brand, a one and only party... What a huge amount of compatibility issues and debates we could get rid of!
  44. Martin S.
    February 17, 2009

    This is really impressive. Thanks for sharing your techniques, man!
  45. inner thoughts
    February 17, 2009

    @Marton Sari: Aah.. your speculations are quite amusing. First off all I'm using Linux as my primary desktop and current HTML environment forces me to use MS proprietary fonts (because HTML cannot handle fonts well, not to say at all!) because most/all sites are "adjuset" for dominant platform (Windows). Also, I'm forced to use Windows under VM for internet banking. Guess what, it requires Windows and IE! And that is all fault of a bad HTML specification! Saying that I want one OS, one brand or whatever just because I feel and know that current HTML is (too) broken is just insane! FYI, when I say "unified server and client side programming" I mostly refer to ability for my code (compiled/uncompiled) to seamlessly "travel" between server and client side, not just data - like it is now. Like I said, I cannot be elaborate in this comment area, and for sure I don't think that I alone can make an alternative - this is multidisciplinary task where all interested sides should contribute - from designers, content writers, users, programmers, sysadmins, etc... Once again, my apology to cssglobe for littering his site with something unrelated . This is final EOD from me on this subject!
  46. Athos
    February 17, 2009

    @inner thoughts: "And that is all fault of a bad HTML specification!" IMHO that is all fault of a company doing it's "best" to win the browser-wars back in the '90s. And they are still doing the same - see what Microsoft is planning about standards-compliant mode in IE8. Again.
  47. Fadel
    February 17, 2009

    not work in ie6
  48. Paul Armstrong
    February 18, 2009

    This seems like another case of using CSS for the sake of using CSS. It would be much simpler, semantically correct, usable, and accessible to have used a straight HTML table, hidden it off screen with a negative absolute position, and replaced it with an image via CSS. After all, a line graph is tabular data and deserves to be treated as such.
  49. Zachary Johnson
    February 18, 2009

    Dean and Paul both make the good point that, as far as markup goes, this would be the place to be using a table. When it comes to actually using a line chart on a website, I am either going to want to download/hotlink a rendered image of the chart OR I am going to want a table of the data in the chart. In this case my choices are taking a screen shot myself or grabbing the weird definition list.
  50. Lorne Pike
    February 22, 2009

    Very cool to continually see different ways that people can take the same code and find completely new ways to create with it. Thanks for the lesson!
  51. Web Design Creatives
    February 24, 2009

    Brilliant thought and hard work, really admirable! It is a great source of inspiration to do more wonders. Thanks!
  52. vishal
    March 24, 2009

    Pure CSS is a better option because at times people may have javascript disabled and their browsers may not be having FLASH plugins installed. This piece of information which you have provided is a nice way to derive a line graph using pure CSS. Thanks for this Post!
  53. Sean Olson
    April 1, 2009

    @cssglobe It really does look very nice, and the thought that goes into your CSS projects is always noticeable. The one question I have is if this can plot data from MySQL... Would you just place your aliases/queries between the em tags like so? <em>'.$rows.'</em> I'm developing a chart for tracking real-time statistics for our company's intranet site, and we have a gorgeous bar graph plotting data from MySQL... I've been up to this point completely unsuccessful getting the same functionality out of a line graph (which is what management wants). Any insight you can offer is appreciated. @inner thoughts: Show me another language that can render graphical elements better than CSS using syntax that is JUST AS EASY and I'll be happy to try it. CSS is very powerful stuff, and is only becoming more so with time. You're entitled to your opinion that HTML and everything related to it sucks, but I have to agree with others here-- Yes, in this case the burden is on YOU to come up with a better alternative. All of our web standards are broken? Fix them or shut up and learn to deal with it like the rest of us.
  54. PJ
    April 11, 2009

    It's very clever. Creative. And innovative. Geez people will gripe, won't they? Folks like you thinking up things like this are often the seed of other people coming up with sparked ideas that continue a given line of logic in a different way. If nothing else it's a great exercise in CSS and logic.
  55. cssrain
    April 13, 2009

    oh,I never thinked so.
  56. Hans Lee
    April 20, 2009

    Here is my attempt to convert image to HTML and CSS. No hack. Of course, the technique could be used in drawing pure css line graph. It's possible to draw multiple lines on the same graph.
  57. Gerd
    June 18, 2009

    Thats really awesome. Its good to know a tech. to get lost from js etc.
  58. thuc pham minh
    June 18, 2009

    U 've made a great work. I'm using your line chart for my thesis and til now it works very well. I appreciate you so much.
  59. Lucy
    June 23, 2009

    seems a really complicated and complex way of doing something jscript or flash could do much easier, but it is a lovely demonstration of what CSS (and images ;) ) can do all by themselves!
  60. jay
    June 26, 2009

    Figure i should point out that there's a typo in... "top values which shits sprite image up". Now if my top values actually did shit my sprite images up, id probably be quite amused. lol. ok onward with the debates

Sorry, the comment form is closed at this time.