Spinner
<o-spinner> tells people something is loading, in five variants that share one size, speed and color.
Each variant is a small Orbit universe. The ring is two equal <o-arc>s turning at two paces, so the arc they draw together stretches and shrinks. Dots are satellites on one ring, segments are vectors, and the orbit variant turns two rings of satellites around a core. All of it moves with CSS, so a spinner runs no script while it turns.
Attributes
| Attribute | Default | What it does |
|---|---|---|
variant | ring | ring, dots, segments, orbit or progress. |
value | With variant="progress", how much is done. Without it the progress ring turns like ring; set it and it fills to the value. Remove it to go back. | |
min / max | 0 / 100 | The range of value. See min, max and step. |
readout | off | Shows the value in the middle of a progress ring: the share done, like 64%, unless a format is set. |
label | Loading | The accessible name: what is loading. |
size | 48px | Width of the spinner. Everything inside scales with it, from 16px in a button to a full screen. |
speed | 1 | Seconds per cycle. Each variant keeps its own rhythm around it. |
color | #4fd1c5 | Arcs, dots and ticks. Sets --ok-spinner-color. |
track | faint gray | The ring behind the arcs and the orbit lines. Sets --ok-spinner-track. |
accent | #ffb547 | The small moons of the orbit variant. Sets --ok-spinner-accent. |
count | 8 dots, 12 segments, 2 moons | How many dots, ticks or moons. |
thickness | 2, 1.8 for progress | Ring thickness in lanes. A lane is a twelfth of the radius. |
shape | rounded | Ending of the arcs: any Orbit shape. |
paused | off | Stops every animation where it is. |
format, decimals, currency, locale, unit | Number format of the readout and aria-valuetext. See Shared options. | |
theme | dark, light or glass. Also inherited from an ok-theme-* class on a container. See Shared options. |
Properties
| Name | What it does |
|---|---|
value | The progress value, kept in range, or undefined while there is none. Setting it writes the attribute; null removes it. |
formatter | A function (value, { kind, min, max }) => string for the readout and aria-valuetext. See Shared options. |
Progress
When you know how far along a task is, say so. The progress ring turns while there is no value and fills once there is one, gliding from one value to the next.
Styling
| Property | Default | What it does |
|---|---|---|
--ok-spinner-color | var(--ok-fill, #4fd1c5) | Arcs, dots, ticks and the orbit planet. |
--ok-spinner-track | var(--ok-track, rgba(127,127,127,.2)) | Track and orbit lines. |
--ok-spinner-accent | var(--ok-accent, #ffb547) | Moons of the orbit variant. |
--ok-spinner-speed | 1s | Seconds per cycle. |
--ok-spinner-weight | 1 | Thickness of the segment ticks. |
--ok-font-size | 17cqmin | Size of the readout, as a share of the spinner. |
More examples
Inside a button
A full-screen loader
On a light page
Accessibility
The spinner has role="progressbar" and aria-busy="true", named by label (“Loading” by default; say what is loading). While there is no value it has no aria-valuenow, which is how a progress bar says it does not know how far along it is. With a value it gets aria-valuenow, aria-valuemin, aria-valuemax and an aria-valuetext in the number format, and aria-busy turns false at the end. Set role="status" yourself if the spinner should be announced as it appears; the spinner keeps it. It is never a tab stop.
With prefers-reduced-motion nothing turns or swells. The arcs, dots, ticks and moons stay in place and breathe slowly in and out, so the page still shows it is working, and a progress ring jumps straight to each new value.