Skip to content

Progress Ring Indeterminate

Without a value, the ring is indeterminate: it spins with a built-in animation and sets the --indeterminate CSS state. Assign a number to leave the state, or null to return to it; replace the animations via :state(--indeterminate)::part(svg) and ::part(fill).

Loading Assets

%

Code

The following example assumes that you have imported the component and set up the theme.

Progress Ring
<div class="progress-container">
<h3 id="progress-ring-label">Loading Assets</h3>
<!-- No `value` attribute: the ring starts indeterminate -->
<sv-progress-ring id="progress-ring" aria-labelledby="progress-ring-label">
<span data-percentage="0"></span>
<span>%</span>
</sv-progress-ring>
<button id="toggle-button" type="button" class="update-button">Finish Loading</button>
</div>
<script type="module">
12 collapsed lines
/** @type {HTMLButtonElement} */
const toggleButton = document.querySelector("#toggle-button");
/** @type {ProgressRing} */
const progressRing = document.querySelector("#progress-ring");
toggleButton.addEventListener("click", () => {
// Setting the value to `null` returns the ring to the indeterminate state
const isIndeterminate = progressRing.value === null;
progressRing.value = isIndeterminate ? 100 : null;
toggleButton.textContent = isIndeterminate ? "Load Again" : "Finish Loading";
});
</script>
<style>
30 collapsed lines
.progress-container {
display: flex;
flex-direction: column;
gap: 1em;
align-items: center;
}
sv-progress-ring {
inline-size: 100%;
max-inline-size: 200px;
margin-block: 1em;
span {
font-family: monospace;
font-size: 2rem;
}
}
sv-progress-ring:state(--indeterminate) span {
visibility: hidden;
}
.update-button {
padding: 0.5em 1em;
color: var(--sv-accent-content);
cursor: pointer;
background-color: var(--sv-accent);
border: none;
border-radius: var(--sv-bdr-rad-md);
}
</style>