Progress Ring Examples
The examples below assume that you have imported the component and set up the theme.
Basic
Set value within the min/max range, and the fill animates to every assigned value. The ring fills the element, so give it a size.
<div class="ring-basic"> <sv-progress-ring aria-label="Upload progress" value="65"></sv-progress-ring></div>
<style> .ring-basic { display: flex; justify-content: center; padding-block: 1em;
sv-progress-ring { inline-size: 6rem; } }</style>Indeterminate
Without a value, the ring is indeterminate and spins until one is assigned.
Your system is set to reduce motion, so a short arc sits still at the top of the ring.
<div class="ring-indeterminate"> <sv-progress-ring aria-label="Loading"></sv-progress-ring></div>
<style> .ring-indeterminate { display: flex; justify-content: center; padding-block: 1em;
sv-progress-ring { inline-size: 3rem; } }</style>Content
Slotted content is centered inside the ring. A child with data-percentage or data-value renders the current number, and the attribute's number sets the decimal places. A data-value-text element supplies aria-valuetext, since slotted content is hidden from assistive technology.
%
of 8
<div class="ring-content"> <sv-progress-ring aria-label="Storage used" value="81.5"> <p data-value-text> <span data-percentage="1"></span> <span>%</span> </p> </sv-progress-ring>
<sv-progress-ring aria-label="Downloaded episodes" max="8" value="3"> <p data-value-text> <span data-value></span> of 8 </p> </sv-progress-ring></div>
<style> .ring-content { display: flex; flex-wrap: wrap; gap: 2em; justify-content: center; padding-block: 1em;
sv-progress-ring { inline-size: 6rem; }
p { margin: 0; font-size: 0.875rem; } }</style>Download
Assign value from JavaScript whenever progress arrives, and the fill animates to it on its own.
%
<div class="ring-download"> <sv-progress-ring class="download-ring" aria-label="Download progress" value="0"> <p data-value-text> <span data-percentage="0"></span> <span>%</span> </p> </sv-progress-ring></div>
<script type="application/x-typescript" module> const ring = document.querySelector<ProgressRing>(".download-ring")!;
let speed = 100;
function tick() { const current = ring.value ?? 0; const next = current >= ring.max ? 0 : current + 1;
ring.value = next;
if (Math.random() < 0.1) { speed = 20 + Math.random() * 380; }
setTimeout(tick, next >= ring.max ? 1500 : speed); }
tick();</script>
<style> .ring-download { display: flex; justify-content: center; padding-block: 1em;
sv-progress-ring { inline-size: 6rem; }
p { margin: 0; font-size: 0.875rem; } }</style>Styling
Custom properties control the thickness, line cap, fill direction, and colors of the ring.
<div class="ring-styling"> <sv-progress-ring class="thick" aria-label="Thick ring" value="65"></sv-progress-ring> <sv-progress-ring class="counter" aria-label="Counter-clockwise ring" value="65"></sv-progress-ring> <sv-progress-ring class="tinted" aria-label="Tinted ring" value="65"></sv-progress-ring></div>
<style> .ring-styling { display: flex; flex-wrap: wrap; gap: 2em; justify-content: center; padding-block: 1em;
sv-progress-ring { inline-size: 6rem; }
.thick { --sv-progress-ring-track-thickness: 8px; --sv-progress-ring-fill-thickness: 12px; --sv-progress-ring-fill-linecap: butt; }
.counter { --sv-progress-ring-clockwise: -1; }
.tinted { --sv-progress-ring-fill-clr: #22c55e; --sv-progress-ring-track-clr: color-mix(in srgb, #22c55e 25%, transparent); --sv-progress-ring-bg: color-mix(in srgb, #22c55e 10%, transparent); } }</style>Dashed
Split the fill into dashes with --sv-progress-ring-dash-num, and set the space between them with --sv-progress-ring-dash-gap.
<div class="ring-dashed"> <sv-progress-ring class="few-dashes" aria-label="Ring with 12 dashes" value="65"></sv-progress-ring> <sv-progress-ring class="many-dashes" aria-label="Ring with 40 dashes" value="65"></sv-progress-ring> <sv-progress-ring class="many-dashes" aria-label="Loading"></sv-progress-ring></div>
<style> .ring-dashed { display: flex; flex-wrap: wrap; gap: 2em; justify-content: center; padding-block: 1em;
sv-progress-ring { --sv-progress-ring-track-thickness: 12px; --sv-progress-ring-fill-thickness: 12px; --sv-progress-ring-fill-linecap: butt;
inline-size: 6rem; }
.few-dashes { --sv-progress-ring-dash-num: 12; --sv-progress-ring-dash-gap: 6px; }
.many-dashes { --sv-progress-ring-dash-num: 40; --sv-progress-ring-dash-gap: 3px; } }</style>