Explain Codes LogoExplain Codes Logo

Css Progress Circle

html
responsive-design
css-animations
css-variables
Anton ShumikhinbyAnton Shumikhin·Feb 4, 2025
TLDR

Create a CSS Progress Circle using SVG and two powerful CSS properties: stroke-dasharray and stroke-dashoffset. Use stroke-dashoffset to control the circle's progress.

Here's an example for a 50% progress:

<svg viewbox="0 0 36 36"> <!-- Base circle --> <circle cx="18" cy="18" r="16" stroke="#eee" fill="none" stroke-width="4"/> <!-- Progress circle: tours around like it lost its keys --> <circle cx="18" cy="18" r="16" stroke="#f06" fill="none" stroke-width="4" stroke-dasharray="100" stroke-dashoffset="50" /> </svg>

Key Points:

  • SVG's second <circle> shows progress.
  • The dash length is set by stroke-dasharray="100".
  • A half-filled circle (50% progress) is created by stroke-dashoffset="50".
  • Modify stroke-dashoffset to depict different percentages.

Using CSS to further enhance your progress circle

Animation with keyframes

Make your static circle come to life with CSS animations using @keyframes. This will create a visually engaging experience for your users.

@keyframes fill { to { /* Makes the circle fill up quicker than you can say 'pseudopseudohypoparathyroidism' */ stroke-dashoffset: 0; } } .progress-circle { animation: fill 2s ease-out forwards; }

Ensure your animations run smoothly on all browsers by adding -webkit prefixes.

@-webkit-keyframes fill { to { stroke-dashoffset: 0; } }

Dynamic control using CSS variables

Use a CSS variable --progress to dynamically define how much of the circle is filled by modifying stroke-dashoffset.

:root { /* Ranging from going for that last piece of pizza to resisting the temptation */ --progress: 75; } .progress-circle { stroke-dashoffset: calc(100 - var(--progress)); }

You can update the progress more conveniently directly in the HTML:

<style> .progress-circle { stroke-dashoffset: calc(100 - var(--progress)); } </style> <svg style="--progress:30;"> <!-- circle elements --> </svg>

Stylish fills using gradients and shadows

Utilize linear gradients and box-shadows for a sophisticated look that screams, "Look at me, I'm attractive!"

.progress-circle { stroke: linear-gradient(to right, #f06, #aef); box-shadow: 0px 0px 10px #ccc; /* Subtle shadow for that 3D oomph */ }

Positioning progress elements using flexbox

Ensure your CSS Progress Circle is centered and responsive on all screen sizes. So, even if your users are on giant 4k monitors or teeny-tiny mobile screens, your circle looks centered...like that one overachiever we all know.

.container { display: flex; justify-content: center; /* Horizontally centered like a star in the night sky */ align-items: center; /* Vertically centered, like the cream in an Oreo */ height: 100vh; }

Going further with CSS enhancements

Conic gradients for a color transition effect

Want to make your circle look funkier? How about let your colors transition as the progress changes? Just like an animated color wheel. Fasten your seat belts; this ride is about to get colorful!

.progress { background-image: conic-gradient(#f06 0%, #aef var(--progress), #eee var(--progress)); }

Using transforms for additional niceties

Make your circle react to user interaction. Let's make the circle grow bigger when users hover over it. Because who doesn't like something that reacts to their every move?

.progress-circle:hover { transform: scale(1.1); /* I'm growing bigger! */ transition: transform 0.3s ease-in-out; /* Smooth as a jazz saxophone solo */ }

Making progress dynamic with JavaScript

Despite our pure CSS agenda, a small detour to JavaScript town wouldn't hurt. It's essential to know how to manage progress dynamically when user interaction comes into play.

document.querySelector('.progress-button').addEventListener('click', function() { var circle = document.querySelector('.progress-circle'); var progress = parseInt(circle.style.getPropertyValue('--progress'), 10); progress = (progress + 10) % 100; /* Because there's always room for progress */ circle.style.setProperty('--progress', progress); });