How to Create CSS3 Pie Charts
January 27th, 2011 by Kyle J. Larson
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:
- In the article the pie pieces are pulled out from the sphere and I wanted a solid circle.
- 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.
- 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.
24 Comments
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?
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;}
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.
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.
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?
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?
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.
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.
Günther Leenaert
For cross-browser isomorphic pages, I use Eric Meyer CSS reset, which also fixes issues like these.
frank
using the :hover on the slices is dodgy to me, any solutions?
oudin
any idea on how to make it responsive?
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
Kyle Larson
Thanks and nice work Kris!
Usman Hanif
how can I increase the size of pie chart. its very small in size
Freechart
Thanks for such a useful information.Its really helpful to create interactive charts.
But there are number of free charts available in market you can check those charts.
http://www.koolchart.com
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