Skip to the content
Dieter Peirs

Simple SVG pie charts

Posted on:

There's plenty of Javascript libraries available for graph generation but if you just need a simple pie chart, an svg and a bit of clever CSS can do the trick.

TLDR: see the demo on Codepen.

A pie chart is just some circles

To start we need an svg element. For a pie chart with three sections we need three equal circles.

<svg viewBox="0 0 100 100" class="chart">
  <circle r="25" cx="50" cy="50" class="pie pie--value-one"/>
  <circle r="25" cx="50" cy="50" class="pie pie--value-two"/>
  <circle r="25" cx="50" cy="50" class="pie pie--value-one"/>
</svg>

Setting the values

To display the values we can use css variables. If your values come from a database we can render these inline in a style tag in the html.

<style>
  .pie {
    --value-one: 23;
    --value-two: 37;
    --value-three: 40;
  }
</style>

For now we added our values based on a total of 100%. But there's a small caveat with using these values in CSS.

To render the sections of a pie chart we use stroke-dasharray.

.pie--value-one {
  stroke-dasharray: var(--value-one) 158;
}

You might notice the magic 158 number. That's the total length of the gap in the stroke-dasharray. So we need to pass our value in relation to that gap.

We could calculate this in css with the calc() function but stroke-dasharray does not support calc(). So the easiest way to do this is to calculate these values in your backend and render the calculated values for the css variables.

<style>
  .pie {
    --value-one: 36.34; /* Original value 23% (20/100*158) */
    --value-two: 58.46; /* Original value 37% (30/100*158) */
    --value-three: 63.2; /* Original value 40% (50/100*158) */
  }
</style>

Offsetting the sections

To complete our pie chart visualisation we need to offset the sections so they don't overlap. For this we can simply rotate the circles with the sum of the previous values.

.pie {
  transform: rotate(var(--offset)); /* We set the rotate variable in each section */
  transform-origin: center center;
}

.pie--value-one {
  /* nothing to rotate here as it's the first section */
  stroke-dasharray: var(--value-one) 158;
}

.pie--value-two {
  --offset: calc(((var(--value-one) / 158) * 360) * 1deg);
  stroke-dasharray: var(--value-two) 158;
}

.pie--value-three {
  --offset: calc((((var(--value-one) + var(--value-two)) / 158) * 360) * 1deg);
  stroke-dasharray: var(--value-two) 158;
}

You might notice that the first section doesn't start at the top. To fix that we rotate the pie chart 90deg counter clockwise.

.chart {
  transform: rotate(-90deg);
}

Adding some color

For the colors we set some color variables which we can then use for the sections and the chart legend.

:root {
  --value-one-color: green;
  --value-two-color: orange;
  --value-three-color: indigo;
}

.pie--value-one {
  stroke: var(--value-one-color);
}

.pie--value-two {
  --offset: calc(((var(--value-one) / 158) * 360) * 1deg);

  stroke: var(--value-two-color);
  stroke-dasharray: var(--value-two) 158;
}

.pie--value-three {
  --offset: calc((((var(--value-one) + var(--value-two)) / 158) * 360) * 1deg);

  stroke: var(--value-three-color);
  stroke-dasharray: var(--value-three) 158;
}

The result

See the full result on Codepen.


Tagged with:

Hi, nice to meet you!

Ghent, Belgium

Website

Throughout the previous 20 years, my role has revolved around design and front-end development for websites and applications. My focus lies in crafting projects that prioritize sustainability, user-friendliness, and inclusivity.

You can hire me for:

  • Design systems
  • Pattern libraries
  • Prototyping
  • Custom CSS frameworks
  • Accessibility
  • Coaching

Get in touch

Profile picture of Dieter Peirs