I am trying to create a pie chart using circle element in svg. I am able to fill values to 60%, 30% and 10% but all the circle starting from same position.
How can I make next circle start from where previous one ended?
svg { transform: rotate(-90deg); }
circle {
stroke-width: 3;
stroke-opacity: 1;
fill: none;
}
circle.stroke-yellow {
stroke: yellow;
stroke-dasharray: calc(2*3.14*50*60/100),calc(2*3.14*50);
}
circle.stroke-red {
stroke: red;
stroke-dasharray: calc(2*3.14*50*30/100),calc(2*3.14*50);
}
circle.stroke-blue {
stroke: blue;
stroke-dasharray: calc(2*3.14*50*10/100),calc(2*3.14*50);
}
<svg xmlns="http://www.w3.org/2000/svg" height="220">
<circle class="stroke-yellow" cy="110" cx="110" r="50"></circle>
<circle class="stroke-red" cy="110" cx="110" r="50"></circle>
<circle class="stroke-blue" cy="110" cx="110" r="50"></circle>
</svg>
Also stroke-width is not working which I mentioned in CSS.
As @enxaneta mentioned: you will need to give each pie segment an offset by changing the dash-offset property.
Based on your code example:
svg {
transform: rotate(-90deg);
}
circle {
stroke-width: 3;
stroke-opacity: 1;
fill: none;
}
.stroke {
stroke-width: 100;
--circumference: 314.159
}
circle.stroke-blue {
stroke: blue;
stroke-dasharray: calc( var(--circumference) * 10 / 100), var(--circumference);
stroke-dashoffset: 0;
}
circle.stroke-red {
stroke: red;
stroke-dasharray: calc( var(--circumference) * 30 / 100), var(--circumference);
stroke-dashoffset: calc( 0 - var(--circumference) * 10 / 100);
}
circle.stroke-yellow {
stroke: yellow;
stroke-dasharray: calc( var(--circumference) * 60 / 100), var(--circumference);
stroke-dashoffset: calc( 0 - var(--circumference) * 40 / 100);
}
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 220 220" height="220">
<circle class="stroke stroke-blue stroke-10" cy="110" cx="110" r="50" />
<circle class="stroke stroke-yellow stroke-60" cy="110" cx="110" r="50" />
<circle class="stroke stroke-red stroke-30" cy="110" cx="110" r="50" />
</svg>
stroke-width needs to be '100' (radius*2);
Drawbacks:
calc() (SVG pie-chart working only in Chrome, not in Firefox)Recommendations:
Example showing 2 slightly different svg setups:
body{
font-family: arial;
font-size:10px;
}
.icon-wrp {
position: relative;
display: inline-block;
width: 200px;
vertical-align: top;
}
.icon-wrp p{
font-size:12px;
}
<!--simple pi -->
<div class="icon-wrp">
<svg class="svgPieAsset" viewBox="0 0 63.6619772368 63.6619772368">
<symbol id="slice">
<circle transform="rotate(-90 31.8309886184 31.8309886184)" id="circle" class="percent" cx="50%" cy="50%" r="15.9154943092" fill="none" stroke-width="31.8309886184" />
</symbol>
<!--actual pi slices -->
<use class="segment" href="#slice" stroke="green" stroke-dashoffset="0" stroke-dasharray="30 100" />
<use class="segment" href="#slice" stroke="orange" stroke-dashoffset="-30" stroke-dasharray="60 100" />
<use class="segment" href="#slice" stroke="purple" stroke-dashoffset="-90" stroke-dasharray="10 100" />
</svg>
<p>1. Precice geometry based on PI. <br>Should be rendered fine on all browsers.</p>
</div>
<div class="icon-wrp">
<svg class="svgPieAsset" viewBox="0 0 100 100">
<symbol id="slice2">
<circle transform="rotate(-90 50 50)" id="circle" class="percent" cx="50%" cy="50%" r="25" fill="none" stroke-width="50%" pathLength="100" />
</symbol>
<!--actual pi slices -->
<use class="segment" href="#slice2" stroke="green" stroke-dashoffset="0" stroke-dasharray="30 100" />
<use class="segment" href="#slice2" stroke="orange" stroke-dashoffset="-30" stroke-dasharray="60 100" />
<use class="segment" href="#slice2" stroke="purple" stroke-dashoffset="-90" stroke-dasharray="10 100" />
</svg>
<p>2. Using pathLength="100". <br>Might show a tiny gap on chromium based browsers.</p>
</div>
1. left example: Is using a precice (PI based) circle geometry
The desired circumference of the circle element should be 100 svg units.
Therfore we'll need to set the ideal values like so:
radius: 15.91549430919 (100/2π)
stroke-width: 31.8309886184 (2r)
vieBox width/height: 63.6619772368 (4r)
2. right example: Is using pathLength="100"
PathLength allows us to use any circle dimensions by setting the path's length computation value to "100".
Unfortunately, you might encounter rendering imprecisions on some browsers (e.g. chromium based) resulting in visible gaps between pie segments.

Quite likely, this issue will be fixed in future versions of chromium.
Display pie segments
Eitherway, you can now easily display a percentage based pie segment/slice by setting a stroke dash length value:
Example 30% dash length; offset. 0 (since it's the first segment):
<circle stroke-dashoffset="0" stroke-dasharray="30 100" cx="50%" cy="50%" r="15.9154943092" fill="none" stroke-width="31.8309886184" />
Adding pie segments:
You'll need to decrement (as we need negative values) the dash-offset values progressively by subtracting the previous dash length (percentage):
0, -30, -90
Example: 60% dash length; offset. -30
<circle stroke-dashoffset="-30" stroke-dasharray="60 100" cx="50%" cy="50%" r="15.9154943092" fill="none" stroke-width="31.8309886184" />
Example optimized for reusability (using css variables)
.icon-wrp {
position: relative;
display: inline-block;
width: 200px;
vertical-align: top;
}
.chart {
width: 1em;
height: 1em;
font-size: var(--chartFontSize);
}
.segment {
stroke-dasharray: var(--percent) 100;
stroke-dashoffset: var(--offset);
stroke: var(--strokeColor);
}
.chartAni .segment {
animation-name: progress;
animation-fill-mode: forwards;
animation-delay: 0.3s;
animation-duration: 0.5s;
transition: 0.3s;
stroke-dasharray: 0 100;
}
@keyframes progress {
from {
stroke-dasharray: 0 100;
stroke-dashoffset: 0;
}
to {
stroke-dasharray: var(--percent) 100;
stroke-dashoffset: var(--offset);
}
}
<!-- pie asset – hidden -->
<svg class="svgPieAsset" style="display:none" viewBox="0 0 63.6619772368 63.6619772368">
<symbol id="slice" viewBox="0 0 63.6619772368 63.6619772368">
<circle transform="rotate(-90 31.8309886184 31.8309886184)" id="circle" class="percent" cx="31.8309886184" cy="31.8309886184" r="15.9154943092" fill="none" stroke-width="31.8309886184" />
</symbol>
</svg>
<!-- visible pie chart -->
<div class="icon-wrp">
<svg id="pieChart01" class="chart chartAni" style="--chartFontSize:20vw">
<use class="segment" href="#slice" style="--offset:-0; --percent:33.333; --strokeColor:green" />
<use class="segment" href="#slice" style="--offset:-33.333; --percent:33.333; --strokeColor:purple" />
<use class="segment" href="#slice" style="--offset:-66.666; --percent:33.333; --strokeColor:gray" />
</svg>
</div>
Edit: donut chart example
For a donut chart or a circular gauge – just adjust the stroke-width to your needs.
.icon-wrp {
position: relative;
display: inline-block;
width: 200px;
vertical-align: top;
}
.chart {
width: 1em;
height: 1em;
font-size: var(--chartFontSize);
}
.segment {
stroke-dasharray: var(--percent) 100;
stroke-dashoffset: var(--offset);
stroke: var(--strokeColor);
}
.chartAni .segment {
animation-name: progress;
animation-fill-mode: forwards;
animation-delay: 0.3s;
animation-duration: 0.5s;
transition: 0.3s;
stroke-dasharray: 0 100;
}
@keyframes progress {
from {
stroke-dasharray: 0 100;
stroke-dashoffset: 0;
}
to {
stroke-dasharray: var(--percent) 100;
stroke-dashoffset: var(--offset);
}
}
<!-- pie asset – hidden -->
<svg class="svgPieAsset" style="display:none;" >
<symbol id="slice" viewBox="0 0 33 33">
<circle id="circle" class="percent" cx="50%" cy="50%" r="15.9154943092" fill="none" stroke-width="0.95" />
</symbol>
</svg>
<!-- visible pie chart -->
<div class="icon-wrp">
<svg id="pieChart01" class="chart chartAni" style="--chartFontSize:20vw; transform:rotate(-90deg);">
<use class="segment" href="#slice" style="--offset:0; --percent:10; --strokeColor:blue" />
<use class="segment" href="#slice" style="--offset:-10; --percent:30; --strokeColor:red" />
<use class="segment" href="#slice" style="--offset:-40; --percent:60; --strokeColor:yellow" />
</svg>
</div>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With