Animated progress circle

Written by Minna Ylitalo on 10th June 2021

(Last updated 5th July 2023)

See the Pen Animated progress circle by Liquid Light (@liquidlight) on CodePen.

<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

1. Create your svg with vector design software or find a suitable one online

In the final animation the gray circle is directly underneath to indicate the shape and the top gradient circle is animated. Include both circles in the same <svg> with identical coordinates to layer them.

  • Layer one circle #bar-bg for background, and another #bar for the animated progress bar on top of it
  • stroke-dasharray is the length of the circumference of the circle
  • stroke-dashoffset is used to control the location of a point on the path and this value will be animated later with JS
<svg class="svg" height="220" viewPort="0 0 110 110" version="1.1" xmlns="[<http://www.w3.org/2000/svg>](<http://www.w3.org/2000/svg>)">
    <circle id="bar-bg" r="98" cx="110" cy="110" fill="transparent" stroke-dasharray="615.752" stroke-dashoffset="615.752"></circle>
    <circle id="bar" r="98" cx="110" cy="110" fill="transparent" stroke-dasharray="615.752" stroke-dashoffset="615.752"></circle>
</svg>

2. Set stroke-dashoffset in CSS

  • Set some styles and css animation transition on the circle elements and set background stroke-dashoffset to 0 to cover the whole circle
  • Add a gradient colour to the stroke of your top bar by defining the colours inside the svg and calling it in the CSS
  • I want the animation to start from the top of the circle so I've rotated the whole svg by 90 degrees.
<defs>
    <linearGradient id="linear" x1="0" x2="1" y1="0" y2="0">
		<stop offset="0%"   stop-color="#DD2C41"/>
		<stop offset="100%" stop-color="#202050"/>
	</linearGradient>
</defs>
.svg {
    transform: rotate(-90deg);
    margin: auto;
    circle {
	    transition: stroke-dashoffset 1s linear;
	    stroke-width: 1.5em;
	    stroke: var(--neutralLight);
    }
    #bar-bg {
	    stroke-dashoffset: 0;
    }
    #bar {
	    stroke: url('#linear');
    }
}

3. Create the functionality

  • For this example I've added an input field in the markup to set a value for the progress and limited the value between 0 and 100.
  • For added usability we also want to display the value as a number in the middle of the circle
  • You will need to convert the input % figure to a pixel value for the circle with the equations shown below and set the CSS property for stroke-dashoffset with your Javascript. You have already set your transition on the circle in the CSS file, which defines the animation when the value changes.
var circle = $('.svg #bar'),
r = circle.attr('r'),
c = Math.PI * r * 2,
pct = ((100 - value) / 100) * c; // Calculate the precentage of the svg dasharray length

// Set progress stroke length in css
circle.css({strokeDashoffset: pct});

4. Last thing to do is to display the percentage value in the middle of the circle (replace default 0% set in the html file)

$('.percentage').html(value + '%');

To understand more how line animations with svg's are constructed have a look at this article.

This article was posted in Development by Minna Ylitalo