CSS is amazing — I’m regularly surprised at how far it has come in the years I’ve been using it (~2005 – present). One such surprise came when I noticed this tweet by Shruti Balasa which demonstrated how to create a pie chart using conic-gradient().
It’s fairly straightforward. Here’s a code snippet:
Using this tiny amount of CSS, you can create gradients that start and stop at specific angles and define a color for each ‘segment’ of the pie chart.
Brills, I thought I could use this instead of a charting library for a data dashboard project I’m working on for the new CockroachDB Cloud API, but I had a problem. I didn’t know the values for my chart ahead of time, and the values I was receiving from the API weren’t in degrees!
Here’s a preview link and Open-source repo of how I worked around those two problems, and in the rest of this post, I’ll explain how it all works.
Dynamic Data Values
Here’s some sample data from a typical API response which I’ve sorted by value.
The return value of test_output is an array of the value (in degrees) + the string deg.
This solves one of a two-part problem. I’ll now explain the other part of the problem.
To create a Pie chart using conic-gradient(), you need two deg values. The first is the angle from where the gradient should start, and the second is the angle where the gradient should stop. You’ll also need a color for each segment, but I’ll come to that in a moment.
Using the values from the test_output, I only have the end value (where the gradient should stop). The start angle for each segment is actually the end angle from the previous item in the array, and the end angle is the cumulative value of all previous end values plus the current end value. And to make matters worse, the start value for the first angle needs to be manually set to 0 🥴.
Here’s a diagram to better explain what that means:
If that sounds confusing, it’s because it is, but if you look at the output of a function that can do all this, it might make more sense.
And here’s the function that can indeed do all of this. It uses reduce() to iterate over the data array, performs the necessary addition to calculate the angles, and returns a new set of numbers that can be used to create the correct start and end angles for use in a Chart.
Using the above, you should be looking at a Pie chart. In order to make a Donut chart, I’ll need to explain how to make the hole.
Let’s Talk About the Hole
There’s only really one way you can ‘mask’ off the middle of the Pie chart to reveal the background. This approach involves using a clipPath. This approach looks like the below code snippet. I’ve used this for Donut 1.
Note: The src for Donut 1 can be seen here: components/donut-1.js.
However, there is another way. This approach involves using a <circle /> element and placing it in the center of the pie chart. This will work if the fill of the <circle /> matches the background color of whatever the chart is placed on. In my example, I’ve used a pattern background, and you’ll notice if you look closely at Donut 3 that you can’t see the bubble pattern through the center of the chart.
Note: The src for Donut 3 can be seen here: components/donut-3.js.
IMO the clipPath approach is nicer, but it can be more difficult to amend the path points to get the desired thickness of the hole if you don’t have access to something like Figma or Illustrator.
In my example site, I’m using Tailwind to style ‘all the things’ and by using this trick, I’m able to expose the CSS variables so they can be referred to by their name.
If you want to do the same, you could add a color key to the data array:
However, you might get lucky and be working with an API that actually returns values with an associated color. This is the case with the GitHub GraphQL API. So. I popped together one last example.
You can see this working in your browser by visiting /github, and the src for both the GitHub Donut Chart and Legend can be found here:
I experimented once before with creating Donut Charts using an SVG and the stroke-dashoffset. You can read about that in my article, “Create an SVG Doughnut Chart From Scratch For Your Gatsby Blog.” That approach worked really well, but I think I prefer the approach described in this post. CSS is simply the best!
If you’d like to discuss any of the methods I’ve used here, please come find me on Twitter: @PaulieScanlon.