Spinner
Also called loader, loading indicator, throbber, activity indicator
A small looping animation shown while an operation is in flight, indicating activity but not progress.
Example
Attached to the control that was pressed
Standalone, with an accessible name
Checking availability…
The label carries the meaning — the rotating graphic is marked aria-hidden, so screen readers announce “Saving changes” rather than “image”.
When to use it
- The wait follows a direct action — submitting a form, saving, deleting — and the spinner can sit on the control that was pressed.
- The area is too small for a meaningful skeleton, like inside a button or next to an input.
- You genuinely cannot predict the resulting layout, so a skeleton would guess wrong.
- The wait is short and roughly bounded — under a couple of seconds.
When not to
- Initial page or list loads where the layout is known. A skeleton communicates more and prevents layout shift.
- Operations that take more than a few seconds. Without progress information a spinner is indistinguishable from a hang — use a progress bar and say what is happening.
- Several spinners on one screen. A page of rotating circles reads as chaos; prefer one region-level indicator.
- Blocking the whole screen for something that only affects one part of it.
Trade-offs
- Works at any size and in any container, including inside a button.
- Requires no knowledge of the incoming layout.
- Universally understood — no learning required.
- Carries no progress information, so long waits feel indefinite.
- Does not reserve layout space; content still jumps when it arrives.
- Overuse fragments the page into many small waiting states.
Accessibility
What this pattern needs in order to work for everyone.
- Keyboard
- The spinner itself is not focusable.
- When a button enters a loading state, keep it focused and use `aria-disabled` rather than removing it from the tab order — a disabled button drops focus to the body.
- Roles and state
- Use `role="status"` with `aria-live="polite"` so the state is announced without interrupting.
- Give it an accessible name: visually hidden text like “Saving changes” beats a bare “Loading”.
- Mark the rotating graphic itself `aria-hidden` — the text carries the meaning.
- Focus
- Never move focus when the spinner appears. Focus should stay where the user left it, typically on the control they activated.
In the wild
- Stripe Dashboard — Uses in-button spinners for save actions, keeping feedback attached to the pressed control.
- GitHub — Small inline spinners next to individual items rather than one blocking overlay.
Compared with
Side-by-side breakdowns of patterns that solve a similar problem.