Spinner
A CSS-only animated loading indicator. Communicates asynchronous activity to both sighted users and screen readers via role="status" and an accessible label.
Keyboard interaction
The spinner is a non-interactive status indicator. It receives no keyboard focus and has no keyboard interactions.
| Key | Action |
|---|---|
| — | No keyboard interaction. The spinner is a display-only live region. |
Screen reader behaviour
The following ARIA attributes are managed internally by the component:
| Attribute / Property | Value / Behaviour |
|---|---|
role="status" | Applied to the host element. Creates a polite live region — screen readers will announce the label when the spinner enters the DOM without stealing focus. |
aria-label | Bound to the label prop. Provides the announcement text. Defaults to "Loading". Override with a descriptive value such as "Saving changes" or "Uploading file". |
aria-hidden="true" | Applied to the inner ring element. Hides the purely decorative SVG ring from the accessibility tree — only the host-level role and label are exposed. |
Best practices
- Live region behaviour —
role="status"is a polite live region. The announcement is queued behind the current speech, preventing interruption. If you need an assertive announcement (e.g. an error state spinner), wrap the spinner in an element witharia-live="assertive". - Reduced motion — the spinner respects
prefers-reduced-motion. When enabled, the rotation animation is suppressed. - Colour contrast — the spinner stroke inherits
currentColor. Ensure the surrounding text colour meets the 3:1 WCAG AA contrast requirement for non-text elements against the background. - Label specificity — always provide a meaningful
labelprop that describes the operation in progress. Avoid the generic default when users can benefit from more context.
WCAG 2.2 compliance
1.4.3 Contrast (Minimum) — AAPass
The spinner stroke uses currentColor, inheriting from the surrounding text. Ensure the surrounding colour meets the 4.5:1 minimum ratio.
1.4.11 Non-text Contrast — AAPass
As a non-text graphic element, the ring requires ≥ 3:1 contrast against the background. currentColor ensures this when the parent text colour meets AA.
1.4.5 Images of Text — AAPass
No text is rendered as an image. The label is a genuine text node exposed via aria-label.
2.1.1 Keyboard — APass
The spinner is non-interactive and receives no keyboard focus. No keyboard operation is required.
4.1.3 Status Messages — AAPass
role="status" creates a polite live region. Screen readers announce the label when the spinner enters the DOM without requiring focus.