Home / Dashboard Widgets / Progress Ring Chart
Progress Ring Chart in HTML, CSS and JavaScript
A progress ring shows how close you are to a goal as a ring that fills up. This free template draws one with plain SVG and vanilla JavaScript, no chart library. The example shows daily goals in a language learning app.
What is a progress ring chart?
A progress ring shows how close you are to a goal as a ring that fills up. An empty ring means you have not started, a full ring means the goal is done, and a second lap means you went past it.
Stacking a few rings inside each other shows several goals at once in a small space. People love closing rings, which is why fitness and learning apps use them to keep users coming back.
At a glance
- Best for
- Progress toward two to four goals
- Data you need
- A current value and a target for each goal
- Skip it when
- Comparing sizes between goals. Use bars.
- Made with
- HTML, CSS and vanilla JavaScript. No library.
When to use a progress ring chart
- Daily goals in fitness, learning or health apps
- Project or course completion
- Fundraising or savings progress
- Team targets on a dashboard
When to pick another chart
- Gauge Chart: you show one score against zones, not a goal
- Bullet Chart: you track many targets side by side
What you get in this template
- Three rings inside each other, each with its own color
- Rings fill up with a rounded end cap
- Goals past 100% show a second lap
- A switch between today, yesterday and this week
- Big numbers and what is left to go beside the rings
- Tooltips and a data table
How the code works
Here is a short version of the idea behind this progress ring chart. The full file adds the axis, labels, tooltips, sorting and resizing on top of it.
const goals = [[18, 20, '#ff6b6b'], [34, 40, '#4dabf7'], [3, 3, '#51cf66']];
const cx = 160, cy = 160, width = 28;
const pt = (r, a) => (cx + r * Math.sin(a)) + ',' + (cy - r * Math.cos(a));
goals.forEach(([done, target, color], i) => {
const r = 130 - i * (width + 6), a = Math.min(done / target, 0.9999) * Math.PI * 2;
make('circle', { cx, cy, r, fill: 'none', stroke: color, 'stroke-opacity': 0.2, 'stroke-width': width });
make('path', { d: 'M' + pt(r, 0) + 'A' + r + ',' + r + ' 0 ' + (a > Math.PI ? 1 : 0) + ' 1 ' + pt(r, a), fill: 'none', stroke: color, 'stroke-width': width, 'stroke-linecap': 'round' });
});The example uses four tiny helpers that create SVG shapes. Put them above the code and it runs as is.
const svg = document.querySelector('svg');
function make(tag, attrs) {
const n = document.createElementNS('http://www.w3.org/2000/svg', tag);
for (const k in attrs) n.setAttribute(k, attrs[k]);
svg.appendChild(n);
return n;
}
function drawRect(x, y, width, height, fill) { return make('rect', { x, y, width, height, fill }); }
function drawCircle(cx, cy, r, fill) { return make('circle', { cx, cy, r, fill }); }
function drawLine(x1, y1, x2, y2, stroke, width, dash) {
return make('line', { x1, y1, x2, y2, stroke, 'stroke-width': width || 1, 'stroke-dasharray': dash || 'none' });
}
function drawText(x, y, str, anchor) {
const t = make('text', { x, y, 'text-anchor': anchor || 'start' });
t.textContent = str;
return t;
}How to add it to your website
- Download the file. Click Download HTML file above. You get one file called progress-ring.html with everything inside.
- Change the data. Open the file in any code editor and find the DATA list near the bottom. Replace the names and numbers with your own.
- Change the colors and text. Colors are at the top of the style tag. The title, subtitle and main point are plain HTML near the top of the body.
- Put it online. Upload the file to any host, such as GitHub Pages, Netlify or your own server, or paste it into your site. There is no build step.
Questions people ask
What is a progress ring?
A progress ring is a circle that fills up as you get closer to a goal. It is a round version of a progress bar.
How do I make a circular progress bar in HTML?
Draw a faint full circle as the track, then draw an SVG arc from the top to the angle of your progress. A round line cap gives it the familiar look.
How do I show more than 100%?
Draw a second, slightly thinner arc on top for the part past the goal, like this template does. People instantly read it as an extra lap.
How many rings should I use?
Two to four. More than that and the inner rings get too small to read.
More dashboard widgets

061. Gauge Chart
Example: a hotel Net Promoter Score by quarter
063. KPI Cards with Sparklines
Example: revenue, orders, average order and returns for an online shop
064. Calendar Heatmap
Example: a year of code changes on an open source project
065. Gantt Chart
Example: a cafe renovation plan with tasks and milestones
066. Waterfall Chart
Example: how a bakery turns sales into profit
067. Word Cloud
Example: words guests use in hotel reviews
068. Pictogram Chart
Example: trees planted by a charity each year
069. Radial Bar Chart
Example: monthly sales for a surf shop