CSS Bar Chart Using HTML5 Progress

I published a post about how to make a responsive CSS bar chart a little while back. Since then, several people have asked how to do the same thing, but a horizontal version. That’s what we’re going to cover in this post.

I also saw that Brad Frost made a pretty nifty bar chart on his site, so I figured we could use that as the model for our example. He uses the HTML5 <progress> element to build his, which feels appropriate when dealing with a horizontal layout. Browser support isn’t 100% with this feature, so use this wisely and provide good fallbacks, where possible.

The biggest difference with this bar chart is that it will be completely done in CSS. I used a little Javascript in the vertical version and Brad used some in his to get the animation effect, but I wanted to keep this one pretty straightforward, so we’ll be using CSS for the animations, even though the support is limited.

Here is what we will be creating:

  • Nunchucks

    Progress: 50%
  • Bow Staff

    Progress: 75%
  • Roundhouse Kick

    Progress: 25%

The HTML Setup

<ul class="skill-list">
  
  <li class="skill">
    <h3>Nunchucks</h3>
    <progress class="skill-1" max="100" value="50">
      Skill Level: 50%
    </progress>
  </li>
  
  <li class="skill">
    <h3>Bow Staff</h3>
    <progress class="skill-2" max="100" value="75">
      Skill Level: 75%
    </progress>
  </li>
  
  <li class="skill">
    <h3>Roundhouse Kick</h3>
    <progress class="skill-3" max="100" value="25">
      Skill Level: 25%
    </progress>
  </li>

</ul>

The first thing you’ll notice is that we’re wrapping this in an unordered list &lt;ul&gt; element. I did this because it feels right when displaying a list of items. I’ve given this a “skill-list” class name, but you can use whatever you’d like. For example, if this is a chart outlining your recent projects, you could call it “project-list.” Whatever makes the most sense to you.

That means each line is written using the list item &lt;li&gt; element. I’ve given each of these a “skill” class name and this can also be whatever you’d like.

Inside each list item is our &lt;h3&gt;, which will be the label for the progress bar.

After that is our HTML5 &lt;progress&gt; tag, which will act as the meter itself. Note that the max value is the highest value in the meter (in this example, 100). The value is the number that represents where the progress meter stops. In this example, “25” will be 25% of the max value, 100.

Finally, I’ve included content wrapped in the &lt;strong&gt; tag. This will not actually display in our chart but provides nice context, especially where accessibility is a concern.

Style the Progress Element

Once the HTML is in place, we can start styling. The first thing I would recommend tackling is the &lt;progress&gt; element itself.

By default, &lt;progress&gt; is styled differently, depending on which browser it is viewed on. We can reset that using the appearance property. At time that I am writing this, only Safari and Chrome support this with the -webkit prefix and Firefox with the -moz prefix. I would include the un-prefixed property in there as well for future support.

progress, progress[role] {
  -webkit-appearance: none;
     -moz-appearance: none;
          appearance: none;
  border: none;
  background-size: auto;
  height: 100px;
  width: 100%;
}

In addition to appearance, I removed the border, set the background-size and gave it a height of 100px and a width of 100%. Using 100% for the width will allow this to scale for responsive sites.

Style the List Elements

Next, we’re going to style the unordered list and list items. I gave the &lt;ul&gt; a “skill-list” class and &lt;li&gt; a “skill” class, so let’s apply styles to those classes.

// The unordered list
.skill-list {
  list-style: none;
  margin: 0;
  padding: 1em;
}

// The list item
.skill {
  margin-bottom: 1em;
  position: relative;
  h3 {
    color: #fff;
    font-size: 2em;
    font-family: "Helvetica Neue", arial, sans-serif;
    left: 1em;
    line-height: 1;
    position: absolute;
    top: 1em;
  }
  ::-webkit-progress-value { 
    -webkit-animation: bar-fill 2s;
    width: 0px;
  }
}

// The background colors
.skill-1::-webkit-progress-value {
  background: #ff9e2c;
}

.skill-1::-moz-progress-bar {
  background: #ff9e2c;
}

.skill-2::-webkit-progress-value {
  background: #4ecdc4;
}

.skill-2::-moz-progress-bar {
  background: #4ecdc4;
}

.skill-3::-webkit-progress-value {
  background: #ff6b6b;
}

.skill-3::-moz-progress-bar {
  background: #ff6b6b;
}

The skill-list class defines the unordered list that everything is contained in, so we’ll start there. I set the list-style to none to get rid of the bullet points that would display next to each list item by default. Then, I set the margin to zero and padding to 1em to so our graph has a little breathing room on the page.

The skill class defines the list items that contain our progress bars. I gave this a little space by adding some margin to the bottom and set the position to relative.

Next, I styled the Heading 3, which acts as the label for each list item. I set the color to white, and gave it an absolute position so it will lay right on top of the progress bar and let us push it around using the top and left properties. If your stylesheet already has default styles for &lt;h3&gt;, then you may need to adjust these accordingly to be consistent with your site.

I also nested the WebKit pseudo-element for progress-value and gave it a width and an animation. Firefox unfortunately does not support on the &lt;progress&gt; element yet, so we’ll have to go without. We haven’t defined that animation in our code yet, so let’s do that next.

Finally, I set the &lt;background-color&gt; for the three different skills. Note that the background is set twice for each class because Firefox uses a different pseudo-element for defining the color bar than Chrome and Safari.

Add the Progress Animation

I decided to use CSS3 keyframes to animate this bar chart. As mentioned, this will only work with Chrome and Safari for the time being. You could use some Javascript chops to accomplish the same thing for better cross-browser support, but I see the animation as a nice-to-have feature that won’t break the user experience and want to use as little Javascript as possible.

 // The keyframes
@-webkit-keyframes bar-fill {
  0% { width: 0; }
}

@keyframes bar-fill {
  0% { width: 0; }
}

Here, we define the keyframes for our animation. I’m only defining keyframes for Chrome and Safari using the -webkit prefix since the animation is only supported in those browsers. In this example, we are telling the animation to start at no width so that the bars will animate to their respective widths, based on the <value> properties we defined in the first step.

Putting it All Together

We’ve written our HTML, styled everything in CSS and even added a little support for animation. Putting everything together will give you a CSS bar chart that is responsive without using any media queries and uses no Javascript whatsoever.

Please make sure you consider browser support when using this technique, as it is not support by all browsers, especially older ones. Refer to Can I Use for the latest support information.

[codepen_embed height=”470″ theme_id=”279″ slug_hash=”FyBJk” default_tab=”result”]See the Pen CSS Bar Chart Using HTML5 Progress by Geoff Graham (@geoffgraham) on CodePen.[/codepen_embed]

Other Resources

Creating Responsive CSS Pie Charts

We’re going to learn how to make a CSS pie chart in this post using the Pizza Pie Charts add-on Zurb created for its Foundation framework.

I have tutorials for creating responsive CSS bar charts and CSS bar charts using HTML5 progress, so be sure to check those out if you’re looking bar graphs. In this tutorial, I’m going to walk through how to make simple, responsive pie charts using a tool developed by Zurb.

What makes this so great? These pie charts are a lightweight cocktail of CSS and Javascript and use SVG, meaning they scale to any size without losing any resolution. And, since they are responsive, they are perfect for visualizing data in a way that translates well for any browser size. Plus, I don’t know if you’ve ever tried building your own CSS pie charts before, but it’s a beast. This is easy as, well, pie.

Here is what we will be creating

  • Pepperoni
  • Sausage
  • Cheese
  • Mushrooms
  • Chicken
  • Other

Getting Started

You will need to download and install Zurb Foundation to get started. It’s a pretty simple process if you haven’t installed it before, but is outside the scope of this post. Here’s the documentation to get you going. Set up your new project and you’re good to go.

You can do this without Foundation, but I will write this as if you are using it. The only difference is that Foundation provides some layout options that are baked right into their framework that I will be using in this example. If you roll with your grid, then no a big deal, but I wanted to point that out.

Secondly, you will need to download Pizza Pie Charts. Open the package, drop the CSS and JS files in your directory where you normally store CSS and JS files, then make sure you reference them in your document head. That might look something like this:

<link href="path/to/pizza.css" media="screen, projector, print" rel="stylesheet" type="text/css" />

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="path/to/snap.svg.js"></script>
<script src="path/to/pizza.js"></script>

Note that Pizza Pie Charts requires jQuery, so be sure to reference that if you don’t already.

If you’re like me, I use SASS to write my CSS. Fortunately, Zurb made Pizza Pie Charts super SASS-friendly. I have my own SASS filing system, so I was able to drop the pizza.scss file into my SASS directory and start using it right away without having to add the CSS link to document head like the example above.

Set up the HTML

The beautiful thing about these CSS pie charts is that they use semantic HTML. What does that mean? Basically, all you need to do is write standard HTML markup for an unordered list and Pizza Pie Chart does the rest.

<ul data-pie-id="pizza">
  <li data-value="36">Pepperoni</li>
  <li data-value="14">Sausage</li>
  <li data-value="8">Cheese</li>
  <li data-value="11">Mushrooms</li>
  <li data-value="7">Chicken</li>
  <li data-value="24">Other</li>
</ul>

Note that “pizza” is just my naming convention. You can name this whatever you want, but make sure you use it consistently in the next steps. The data values correspond to the size each ingredient takes up in the pie. The larger the value, the bigger the slice. Just make sure they add up to 100.

Add the Divs

Pizza Pie Charts only requires a single div to work. However, I found that if you want your legend to display on one side of the chart instead of stack on top of it, then you need to add a little more markup. It’s not much, but is necessary to make it work.

  • Pepperoni
  • Sausage
  • Cheese
  • Mushrooms
  • Chicken
  • Other

The required portion is the div that contains the “pizza” ID. The row class will come into play in a couple of steps.

Initialize the Javascript

At its most basic, these CSS pie charts only require a single line of Javascript to work. Add this anywhere in your body:


There are a host of different options you can add to this snippet to customize the pie charts.

{
  donut: false,             // show hole in the center
  donut_inner_ratio: 0.4,   // between 0 and 1
  percent_offset: 30,       // relative to radius
  stroke_color: '#333',
  stroke_width: 0,
  show_percent: true,       // show or hide the 
                            // percentage on the chart.
  animation_speed: 500,
  animation_type: 'elastic' // backin, backout, 
                            // bounce, easein, 
                            // easeinout, easeout,
                            // linear
}

For this example, here is the code I will be using:

In short, this turns the chart from a pie into a donut and moves the percent labels closer to the chart.

Style the Charts in CSS

Now that the HTML and Javascript are completely set up, we can start styling our chart. Notice that we have three elements to play with:

  • .row
  • ul[data-pie-id=”pizza”]
  • #pizza

I always want my legend on the left and my chart on the right. By wrapping our chart in the “row” class, we are using a built-in Foundation component that tells the code that the things inside of it all belong on the same row. If you use SASS, you can use @include to create your own class, or just use this one out of the box. It’s your choice.

Next, go into the pizza.scss file and add these lines to the end:

ul[data-pie-id] {
  list-style: none;
  padding: 10px;
  @include grid-column(4);
}

#pizza { @include grid-column(8); }

We have just told the code to push the legend to the left using four columns in the row and the chart to the right using eight columns in the row. Yes, you can wrap the HTML in those divs, but I tend to favor less divs than more, so this is the way I suggest going about it.

If you use your own grid instead of Foundation, you can replace those @includes with your own column mixin.

Conclusion

That’s it! With a few new files, several lines of HTML and a couple lines of SASS, you can create CSS pie charts that can be used anywhere on your site. No Photoshop or Illustrator. No crazy Javascript wrangling.

Creating a Responsive CSS Bar Chart

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.

<ul>
  <li>95%</li>
  <li>80%</li>
  <li>75%</li>
  <li>40%</li>
</ul>

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.

<ul>
  <li>
    <div class="label">MVP</div>
    <div class="label">All Star</div>
    <div class="label">Slugger</div>
    <div class="label">Rookie</div>
    <div class="label">Triple A</div>
  </li>
  <li>95%</li>
  <li>80%</li>
  <li>75%</li>
  <li>40%</li>
</ul>

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.

.chart { width: 100%; }

.chart li {
  border-radius: 4px 4px 0 0; /* Remember vendor prefixes */
  box-shadow: 0 1px 0 0 rgba(255,255,255,.6) inset; /* Remember vendor prefixes */
  display: block;
  height: 125px;
  padding: 25px 0;
  position: relative;
  text-align: center;
  vertical-align: bottom;
}

.chart .axis { 
  display: none;
  top: -25px;
  width: 11%;
 }

.chart .label {
  background: #eaeaea;
  margin: -.6em 0 65px 0;
}

.chart .percent {
  font-size: 30px;
  letter-spacing: -3px;
  opacity: .4;
  width: 100%;
}

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.”

...

<li class="teal" style="height:95%;">
  <div class="percent">95%
  <div class="skill">Karate%
</li>

...
...

.chart .teal {
background: #4ecdc4;
background-image: linear-gradient(#76d8d1, #4ecdc4 70%);
border: 1px solid #4ecdc4;
}

.chart span { font-size: 30px;  }

...

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.

@media (min-width: 700px) {
  .chart {
    background: url("http://cl.ly/QSpc/bg-chart.png") right top repeat-x;
    height: 425px;
    margin: 0 auto -32px;
  }
  .chart li {
    display: inline-block;
    height: 425px;
    margin: 0 1.8% 0 0;
    width: 14%;
  }
  .chart .axis {
    display: inline-block;
  }
  .chart .percent {
    font-size: 40px;
    position: absolute;
  }
  .chart .skill {
    bottom: 20px;
    font-size: 16px;
    position: absolute;
  }
}

@media (min-width: 1000px) {
  .chart .percent {
    font-size: 62px;
  }
}

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:

Syrupy Responsiveness

In a different lifetime, I remember working at Starbucks at a time the company was shaking things up a bit. In an effort to reduce costs and create more space on the back counters, the company downsized its syrup selection to a modest ten flavors. Those of us that can remember that far back (circa 2003) now relish the days of ordering a hazelnut latte or a valencia mocha without it being a special promotion or holiday. The decision was a little unpopular at the time, but customers loved the speediness and consistency that the efficiency provided.

The same is true with responsive web design. More often than not, the posts I see on the topic are either opinions about the best design approach or a showy piece on how to hit as many viewports as possible. Though they are interesting and certainly contribute to the web community as a whole, I think most of these posts miss the point of responsive web. Whereas one is an extreme towards a one-size-fits-all approach, the other errs on the side of agnosticism to the point of being irrelevant to the user. Instead, I propose a Starbucks syrup approach to responsive design and development.

Understand your customer’s tastes

Now, as a barista I was certainly not on the Starbucks board or anywhere near senior leadership, but I imagine they knew a thing of two about the tastes of customers prior to dropping syrup flavors from the lineup. I’m guessing they poured over sales receipts, surveys and any bit of data they could possibly get their hands on before making a decision.

In the same way, I find it helpful to know a thing or two about the people visiting a website before I determine whether or not a responsive layout is even necessary. Sure, it’s fun to show off your chops and make something that bends and moves when the bottom right corner of a browser is pulled around, but if no one is visiting the site on a mobile device, tablet or anything below 960px, then there’s very little sense in doing the work.

For that reason, I often request access to a client’s analytics account or reports to get a sense for the type of traffic the site attracts. Of course, some clients give me a confused look at the slight mention of “analytics” in which case I try to set them up with a Google Analytics account or a short-term qualitative survey to get the best idea possible.

Eliminate unnecessary options

I love this tweet from Josh Brewer:

Responsive is not simple. It is a chore.

So why make it even harder than it needs to be? By reducing the number of flavors it offers, Starbucks also reduced the number of options for customers to create a personalized drink experience. Doing so not only made the ordering process easier for customers who may have been overwhelmed by too many options, but it smoothed the production process for employees who had to make the drinks.

Until there is a bullet-proof one-size-fits-all way of developing websites (I hope it never happens, personally), it’s virtually impossible to be everything to every person and viewport without a lot of serious tricks, hacks and hard work. And even if you do pull off the impossible, you’re left with a mess of code that is difficult to maintain and probably lowered your hourly rate of return on the project.

Learn what people need from the site and tailor accordingly, eliminating viewports that get little or no traffic in the first place. It’s better to add viewports later than to account for them unnecessarily in the first place. Work smarter, not harder.

Design for the occasion

This has nothing to do with syrups (well, it would be a stretch if I tried), but is worth mentioning because of the hype around whether it’s better to start with mobile or desktop in the responsive design process.

The short answer to me is: it depends.

I was totally on board the first time I heard the mobile-first approach because I love how mobile forces you to get to the core of a site’s purpose before plopping in a bunch of shiny bells and whistles.

But the more I think about it, a mobile-first approach can be discriminating because it puts the needs of one segment over another. The same person visiting a site on a mobile device will probably use it differently on a desktop (depending on the general purpose of the site), because of the context of the visit. Are they on the go and need quick information? Are the in a stationery place and want to have an experience? Are they hanging out on the couch in the mood to consume content? The needs can vary greatly.

For that reason, I feel it’s more necessary to start with the viewport that is most conducive to the primary goal of the site. And if the goal fits one extreme or another, just go with your gut and degin with what makes you most comfortable. No one is going to show up at your door with a death wish for that.

Write opinionated code

I’ve always been a fan of adopting early standards and trying graceful degradation where possible. But I believe that going responsive requires your code to choose sides as far as what browsers it does and does not support. The most obvious example is older IE versions (I’m looking at you, IE8-!) that do not carry support for media queries or HTML5. There are polyfills for that, of course, but there’s no need to bend over backwards for users who are already used to experiencing an outdated and unsatisfying version of the World Wide Web. You probably shouldn’t even be diving into responsive design if a a majority of your visitors are surfing in on IE7 anyways.

Short story: take a side and reward those who choose the same.

Conclusion

I love how responsive design has reinvigorated the web community and created an active dialogue but, as far as standards and best practices are concerned, the craft is still far too new to command a definitive way of getting it done. Until we see a shake-up within the browser community to determine a standard for how pixels dance to the viewport they’re displayed on, it’s best to design for the users and use a process that fits your level of comfort.