Creating a Responsive CSS Bar Chart

July 31, 2013

One of the new features I added to this site when I redeveloped it was a responsive bar chart. It’s helpful for visualizing my skills as a designer and developer, but it could also be helpful for lots of other things, say touting your ninja skills or rating your favorite bands from the 80s. I’ll give a brief explanation of how I created it.

At the end of this, we should end up with something that looks like this:

Responsive CSS Bar Chart

Start with an unordered list

The entire chart is basically an unordered list. That means our HTML is pretty basic.

[[code class="language-html"]]czo3NTpcIjx1bD4NCiAgPGxpPjk1JTwvbGk+DQogIDxsaT44MCU8L2xpPg0KICA8bGk+NzUlPC9saT4NCiAgPGxpPjQwJTwvbGk+DQp7WyYqJl19PC91bD5cIjt7WyYqJl19[[/code]]

Let’s add a y-axis

So far, this will provide us with the bars, along the x-axis, but no y-axis. And, let’s face it, any chart without a scale is pretty sucky. So let’s add one.

[[code class="language-html"]]czoyNzk6XCI8dWw+DQogIDxsaT4NCiAgICA8ZGl2IGNsYXNzPVwibGFiZWxcIj5NVlA8L2Rpdj4NCiAgICA8ZGl2IGNsYXNzPVwibGFiZWx7WyYqJl19XCI+QWxsIFN0YXI8L2Rpdj4NCiAgICA8ZGl2IGNsYXNzPVwibGFiZWxcIj5TbHVnZ2VyPC9kaXY+DQogICAgPGRpdiBjbGFzcz1cImxhYmV7WyYqJl19bFwiPlJvb2tpZTwvZGl2Pg0KICAgIDxkaXYgY2xhc3M9XCJsYWJlbFwiPlRyaXBsZSBBPC9kaXY+DQogIDwvbGk+DQogIDxsaT45NSU8L3tbJiomXX1saT4NCiAgPGxpPjgwJTwvbGk+DQogIDxsaT43NSU8L2xpPg0KICA8bGk+NDAlPC9saT4NCjwvdWw+XCI7e1smKiZdfQ==[[/code]]

Now we have something to measure the height of our bars against. We’re wrapping these values in a list <li>
tag to make it part of the ordered list, but then individually wrapping each one in a div class .label so we can style them separately without affecting the rest of the chart. Basically, the labels have to stack vertically while the bars stack horizontally, so that’s what we’re doing here.

Let’s get some styles up in here

If you were to check the output, you get a pretty gnarly vertical list. Not exactly what we’re after, so let’s add some styles to pretty things up a bit.

[[code class="language-css"]]czo1NjI6XCIuY2hhcnQgeyB3aWR0aDogMTAwJTsgfQ0KDQouY2hhcnQgbGkgew0KICBib3JkZXItcmFkaXVzOiA0cHggNHB4IDAgMDt7WyYqJl19IC8qIFJlbWVtYmVyIHZlbmRvciBwcmVmaXhlcyAqLw0KICBib3gtc2hhZG93OiAwIDFweCAwIDAgcmdiYSgyNTUsMjU1LDI1NSwuNntbJiomXX0pIGluc2V0OyAvKiBSZW1lbWJlciB2ZW5kb3IgcHJlZml4ZXMgKi8NCiAgZGlzcGxheTogYmxvY2s7DQogIGhlaWdodDogMTI1cHg7e1smKiZdfQ0KICBwYWRkaW5nOiAyNXB4IDA7DQogIHBvc2l0aW9uOiByZWxhdGl2ZTsNCiAgdGV4dC1hbGlnbjogY2VudGVyOw0KICB2ZXJ0aWN7WyYqJl19YWwtYWxpZ246IGJvdHRvbTsNCn0NCg0KLmNoYXJ0IC5heGlzIHsgDQogIGRpc3BsYXk6IG5vbmU7DQogIHRvcDogLTI1cHg7DQogIHtbJiomXX13aWR0aDogMTElOw0KIH0NCg0KLmNoYXJ0IC5sYWJlbCB7DQogIGJhY2tncm91bmQ6ICNlYWVhZWE7DQogIG1hcmdpbjogLS42ZW0ge1smKiZdfTAgNjVweCAwOw0KfQ0KDQouY2hhcnQgLnBlcmNlbnQgew0KICBmb250LXNpemU6IDMwcHg7DQogIGxldHRlci1zcGFjaW5nOiAtM3B7WyYqJl19eDsNCiAgb3BhY2l0eTogLjQ7DQogIHdpZHRoOiAxMDAlOw0KfVwiO3tbJiomXX0=[[/code]]

What’s going on here? First of all, we’ve wrapped the entire chart in a .chart class and gave it a 100% width to use the entire viewport.

But, wait. If you see what we have so far, it just looks like percentages that are stacked vertically. Exactly. We’re styling this for mobile first, so that it is optimized for smaller screens. That’s why we’ve styled the list items with display: block.

Next, we removed the axis for the time being so it is hidden on small screens. There’s just no room for it, but we’ll introduce it back in when we progressively enhance the bar chart for larger screens.

Finally, we gave the percentages inside each bar some styling. Note the opacity. This will look just lovely when we give the bars a splash of color. Promise.

Color things in a bit

Let’s add some color classes so our chart pops. Basically, we’re adding a color class to each list item a div for both the percentage and the skills that acts as the labels for the bar. Naturally, we’re creating a different color class for each one, but the example below illustrates “teal.”

[[code class="language-html"]]czoxNDQ6XCIuLi4NCg0KPGxpIGNsYXNzPVwidGVhbFwiIHN0eWxlPVwiaGVpZ2h0Ojk1JTtcIj4NCiAgPGRpdiBjbGFzcz1cInBlcmNlbnRcIj57WyYqJl19OTU8c3Bhbj4lPC9zcGFuPg0KICA8ZGl2IGNsYXNzPVwic2tpbGxcIj5LYXJhdGU8c3Bhbj4lPC9zcGFuPg0KPC9saT4NCg0KLi4uDQpcIntbJiomXX07e1smKiZdfQ==[[/code]]

[[code class="language-css"]]czoxNzg6XCIuLi4NCg0KLmNoYXJ0IC50ZWFsIHsNCmJhY2tncm91bmQ6ICM0ZWNkYzQ7DQpiYWNrZ3JvdW5kLWltYWdlOiBsaW5lYXJ7WyYqJl19LWdyYWRpZW50KCM3NmQ4ZDEsICM0ZWNkYzQgNzAlKTsNCmJvcmRlcjogMXB4IHNvbGlkICM0ZWNkYzQ7DQp9DQoNCi5jaGFydCBzcHtbJiomXX1hbiB7IGZvbnQtc2l6ZTogMzBweDsgIH0NCg0KLi4uDQpcIjt7WyYqJl19[[/code]]

Note that we’ve styled the height of the bar inline rather than in the CSS. We could simply specify the height in the color class for each bar, but I find the inline route to be a little easier to maintain, though I typically loathe inline styles and avoid them like the plague.

Lastly, note the span tag around the percentage character. We’re going to style these separately, keeping the font size small while the numbers get larger. Just a neat stylistic thing.

Now let’s make it responsive

Up to this point, we’ve created something that looks neat but is far from looking like a traditional bar chart:

Responsive Bar Chart Mobile

Let’s add our media queries for tablet and desktop. These may vary for the site you are building.

[[code class="language-css"]]czo1Nzg6XCJAbWVkaWEgKG1pbi13aWR0aDogNzAwcHgpIHsNCiAgLmNoYXJ0IHsNCiAgICBiYWNrZ3JvdW5kOiB1cmwoXCJodHRwOi8ve1smKiZdfWNsLmx5L1FTcGMvYmctY2hhcnQucG5nXCIpIHJpZ2h0IHRvcCByZXBlYXQteDsNCiAgICBoZWlnaHQ6IDQyNXB4Ow0KICAgIG1hcmdpe1smKiZdfW46IDAgYXV0byAtMzJweDsNCiAgfQ0KICAuY2hhcnQgbGkgew0KICAgIGRpc3BsYXk6IGlubGluZS1ibG9jazsNCiAgICBoZWlnaHR7WyYqJl19OiA0MjVweDsNCiAgICBtYXJnaW46IDAgMS44JSAwIDA7DQogICAgd2lkdGg6IDE0JTsNCiAgfQ0KICAuY2hhcnQgLmF4aXMgew0KIHtbJiomXX0gICBkaXNwbGF5OiBpbmxpbmUtYmxvY2s7DQogIH0NCiAgLmNoYXJ0IC5wZXJjZW50IHsNCiAgICBmb250LXNpemU6IDQwcHg7DQoge1smKiZdfSAgIHBvc2l0aW9uOiBhYnNvbHV0ZTsNCiAgfQ0KICAuY2hhcnQgLnNraWxsIHsNCiAgICBib3R0b206IDIwcHg7DQogICAgZm9udC17WyYqJl19c2l6ZTogMTZweDsNCiAgICBwb3NpdGlvbjogYWJzb2x1dGU7DQogIH0NCn0NCg0KQG1lZGlhIChtaW4td2lkdGg6IDEwMDBweCkge3tbJiomXX0NCiAgLmNoYXJ0IC5wZXJjZW50IHsNCiAgICBmb250LXNpemU6IDYycHg7DQogIH0NCn0NClwiO3tbJiomXX0=[[/code]]

What did we do? We changed the orientation of the list items to stack horizontally on larger screens using inline-block and set the height of the chart container to 425px. Remember those inline styles? This is what they are measured against, giving each bar its height relative to 425 pixels. We also introduced a background image to the chart. I know this is supposed to be a pure CSS bar chart, but having a repeating background that provides the horizontal lines across the chart is the only way I could think to create that effect. Maybe someone smarter than me will find a better way and let me know (wink, wink).

[codepen_embed height=”268″ theme_id=”279″ slug_hash=”apukc” default_tab=”result”]See the Pen Responsive CSS Bar Graph by Geoff Graham (@geoffgraham) on CodePen.[/codepen_embed]

Additional Resources: