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 »

Leave a Reply

24 Comments

  1. 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?

  2. 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;}

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

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

  5. 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?

  6. Tyrone Dixon

    Hey, man.

    Thanks a ton for this. I’ve been developing on a system that only has access to its built-in scripting language, html, and CSS. This was a huge help for me. I looped through a whole bunch of people to populate the pie chart based on variables.

    Only thing I’m struggling with is trying to get labels on them (I don’t really do HTML or CSS). I was wondering if you had any kind of ideas for that. (I know this is like 6 years after the post, but still…)

    Thanks
    Tyrone

Back to top