12
Progress ring
A zero-JS conic instrument: a registered @property transitions the sweep, @starting-style provides the one-shot mount draw, and a radial mask cuts the donut so it composes over any background. Soft ease-out only — a reading that overshoots is a false reading.
@property --ring-p@starting-styleconic-gradientmaskThe centered figure SNAPS to the value; only the ring travels. And the ring may approach its reading, never pass it — springs are for chrome, and this is not chrome.
Mount sweep + live value
both are the same CSS transition — no JS animates anything
72%
capacity
38%
91%
Composes over anything
the mask cuts a true hole — no faked inner circle
The whole engine
motion.css §8 — there is no JS to show
@property --ring-p { syntax: "<number>"; inherits: false; initial-value: 0; }
.progress-ring::before {
--ring-p: var(--ring-value, 0); /* host sets 0–100 inline */
background: conic-gradient(
var(--ring-color, var(--accent)) calc(var(--ring-p) * 1%),
var(--ring-track, var(--line-strong)) 0);
mask: radial-gradient(closest-side,
transparent calc(100% - var(--ring-w) - 1px), #000 calc(100% - var(--ring-w)));
transition: --ring-p 900ms var(--ease-out-soft); /* NEVER a spring */
@starting-style { --ring-p: 0; } /* the mount sweep */
}