KYLEJLARSON

How to Create CSS3 Pie Charts

Last week I decided to update my online resume to make it a little more graphical, because well… I’m a designer. The first step was coming up with some good ways to represent data, and pie charts seemed like a good fit to show skill development. Pie charts are pretty simple to create using a spreadsheet program or a drawing program, but I wanted something out of the ordinary that didn’t require creating new graphics every time I update them. It seemed like it should be possible with the new capabilities of CSS3 so I started working on a solution.

The two most promising things I found were Google’s Chart Wizard, (which uses javascript) and a CSS3 Pie Chart Article from Atomic Noggin. I wanted to do something purely with CSS & HTML so I took the ideas from that article and tweaked them a bit to get the result that I wanted.

There were a few things that I wanted to do differently from the original article:

  1. In the article the pie pieces are pulled out from the sphere and I wanted a solid circle.
  2. Once aligned as a solid sphere there were some rendering issues (in some browsers) aligning clipped shapes next to each other that left gaps between the shapes.
  3. I wanted to be able to add styles to the full css pie chart such as a border or drop-shadow.

Creating a Drop-Shadowed Circle

My first step was creating a circle that will be the bottom layer of the chart. This bottom circle will also hold any border or drop-shadow style. Additionally, I’ve put a div with a set height around the circle so it stays inline with the content (as the circles will be absolutely positioned to stay on top of each other). To create a circle, simply add a border-radius that is half the pixel value of the width of a square div. You’ll notice below I’ve used browser specific css tags (e.g. -moz-border-radius) for the CSS3 elements. Currently CSS3 support is varied between browsers. Eventually, as full support is included in browsers, you won’t need them any more and this will be much simpler to manage.

<style>
     .pieContainer {
          height: 100px;
     }
     .pieBackground {
          background-color: grey;
          position: absolute;
          width: 100px;
          height: 100px;
          -moz-border-radius: 50px;
          -webkit-border-radius: 50px;
          -o-border-radius: 50px;
          border-radius: 50px;
          -moz-box-shadow: -1px 1px 3px #000;
          -webkit-box-shadow: -1px 1px 3px #000;
          -o-box-shadow: -1px 1px 3px #000;
          box-shadow: -1px 1px 3px #000;
     } 
</style>
<div id="pieContainer">
     <div class="pieBackground"></div>
</div>

Adding a Slice to the CSS Pie Chart

Next you’ll want to create a half circle by using clipping to hide the 2nd half. Unless you want exactly 50% you’ll need to change the size of that circle by dropping it inside of a div that controls the rotation and use the inner div to adjust the size. For the first slice we’ll start the outer div at 0 degrees, which is the default, so we’ll only need to edit that for additional slices. (* Note that I’m adding to the code above and only displaying the new CSS.)

<style>
     .pie {
          position: absolute;
          width: 100px;
          height: 100px;
          -moz-border-radius: 50px;
          -webkit-border-radius: 50px;
          -o-border-radius: 50px;
          border-radius: 50px;
          clip: rect(0px, 50px, 100px, 0px);
     }
     .hold {
          position: absolute;
          width: 100px;
          height: 100px;
          -moz-border-radius: 50px;
          -webkit-border-radius: 50px;
          -o-border-radius: 50px;
          border-radius: 50px;
          clip: rect(0px, 100px, 100px, 50px);
     }
     #pieSlice1 .pie {
          background-color: #1b458b;
          -webkit-transform:rotate(50deg);
          -moz-transform:rotate(50deg);
          -o-transform:rotate(50deg);
          transform:rotate(50deg);
     }
</style>

<div class="pieContainer">
     <div class="pieBackground"></div>
     <div id="pieSlice1" class="hold"><div class="pie"></div></div>
</div>

Large & Multiple Slices

If you’d like to make a slice take up more than 50% of the pie chart you’ll just need to add another pie div of the same color with a hold div wrapped around it. To add a slice in a new color just change the background color. Below is an example of making a slice over 50% and a second slice of a new color.

<style>
     #pieSliceBlue .pie {
          background-color: #1b458b;
          -webkit-transform:rotate(180deg);
          -moz-transform:rotate(180deg);
          -o-transform:rotate(180deg);
          transform:rotate(180deg);
     }
     #pieSliceBlue2 {
          -webkit-transform:rotate(180deg);
          -moz-transform:rotate(180deg);
          -o-transform:rotate(180deg);
          transform:rotate(180deg);
     }
     #pieSliceBlue2 .pie {
          background-color: #1b458b;
          -webkit-transform:rotate(40deg);
          -moz-transform:rotate(40deg);
          -o-transform:rotate(40deg);
          transform:rotate(40deg);
     }
     #pieSliceRed {
          -webkit-transform:rotate(220deg);
          -moz-transform:rotate(220deg);
          -o-transform:rotate(220deg);
          transform:rotate(220deg);
     }
     #pieSliceRed .pie {
          background-color: #cc0000;
          -webkit-transform:rotate(140deg);
          -moz-transform:rotate(140deg);
          -o-transform:rotate(140deg);
          transform:rotate(140deg);
     }
</style>

<div class="pieContainer">
     <div class="pieBackground"></div>
     <div id="pieSliceBlue" class="hold"><div class="pie"></div></div>
     <div id="pieSliceBlue2" class="hold"><div class="pie"></div></div>
     <div id="pieSliceRed" class="hold"><div class="pie"></div></div>
</div>

IE Fallback

As expected, this doesn’t work in any Internet Explorer browsers below version 9. If you’re concerned about IE users, a simple way to fix this is adding a conditional comment for IE with a jpg of whatever charts you’re trying to display.

Tags: ,

« Older     Newer »
  • http://www.more-web.co.uk Brent French

    Awesome web design please keep up the tutorials!

  • Allison Shapanka

    This is great! Thanks so much. One issue I ran into: The project I’m working on is a single page with a scroll to each section, and a fixed header image. I noticed that when the header scrolls over the pie chart, the “slice” glides over the image, rather than stay underneath (like the body of the pie chart). Any idea why this is happening?

  • http://www.kylejlarson.com Kyle J Larson

    Thanks Allison, I’m glad it was helpful. I think it’s going over the top of your fixed element because of absolute positioning on the pie chart and it coming later in the code than your fixed header. If you assign a z-index with CSS on the header image you should be able to fix it. Like so – #yourHeaderImageID {z-index: 1000;}

  • http://www.thoughtresults.com/ Saeed Neamati

    This was one of the most beautiful implementations I’ve ever seen using CSS3. Great work buddy. However, to add any kind of behavior to this pie chart is not an easy task at all. I still prefer using SVG.

  • http://www.kylejlarson.com Kyle Larson

    Thanks, I really appreciate it. It could be interesting to try and combine with CSS animation, but SVG definitely has an advantage here.

  • Elxis4

    There is a bug is the above concept. If any slice is larger than 180 degrees the pie is generated with uncovered areas. To solve this I split slices bigger than 180 degrees into smaller ones.

  • Pingback: CSS3 + Jquery Ring Progress bar - David Cramer, Developer, Designer

  • http://www.imstanley.com/ Stanley

    In the “Large & Multiple Slices” example the right side of the pie chart is not rounded. I notice this happens when the rotation is set to 180 degree. Any idea how to fix that?

  • http://www.kylejlarson.com Kyle Larson

    Maybe try splitting the 180 into multiple pieces like Elixis4 mentioned here? I can’t seem to recreate this issue, which browser version are you seeing it in?

  • http://www.imstanley.com/ Stanley

    I’m using Google Chrome Version 23.0.1271.97 m
    This is what I see: http://screencast.com/t/tOFQa8z7DfUs
    I tried to view it in Firefox and it looks perfect.

    I found another example at http://atomicnoggin.ca/test/pie-chart.html which is also using the same technique but it doesn’t has the problem when viewing in Google Chrome. Strange.

  • http://www.kylejlarson.com Kyle Larson

    Interesting… Looks like a rendering issue with the windows version of chrome. If you add margin-left: -1px; to #pieSliceBlue .pie that seems to fix it. Looks like for some reason it’s over the edge of the box and that is cutting it.

  • Pingback: 20? CSS ??/????????? | jQuery??? - macapps.asia

  • Günther Leenaert

    For cross-browser isomorphic pages, I use Eric Meyer CSS reset, which also fixes issues like these.

  • Pingback: Themable count-down timer using AngularJS and CSS3

  • frank

    using the :hover on the slices is dodgy to me, any solutions?

  • Pingback: 20 CSS Graph and Charts TutorialsQubeSys

  • oudin

    any idea on how to make it responsive?

  • http://www.kylejlarson.com Kyle Larson

    You should be able to do it with media queries and just make sure to maintain the ratios here (ie 2:1). Here’s an example file: http://www.kylejlarson.com/files/pie_test.html Just shrink the browser to below 600px and you’ll see the size change.

  • Kris Olszewski

    Great tutorial. I took it step further and turned it into a JS driven widget. Check it out: https://github.com/KrisOlszewski/donut-chart

  • http://www.kylejlarson.com Kyle Larson

    Thanks and nice work Kris!

  • Pingback: How to use transform:rotate in CSS with Cytoscape.js? | Technology & Programming

  • Usman Hanif

    how can I increase the size of pie chart. its very small in size

More Posts