interactionbeginner

Spinner

A circular animated indicator that signals an ongoing process with no known completion time.

Plain English

A spinner reassures users that something is happening even when they cannot see progress. Unlike a progress bar, a spinner has no end point — it just communicates "working." Spinners should appear within 100ms of an action triggering a wait. Overusing them erodes trust: if every interaction spins, nothing feels fast. Reserve spinners for genuine unknowns like API calls, not for short operations under 300ms.

Technical

CSS technique — border: 3px solid #e2e8f0; border-top-color: #3b82f6; border-radius: 50%; animation: spin 0.8s linear infinite; @keyframes spin { to { transform: rotate(360deg); } }. Common sizes: 16px (inline text), 24px (inside buttons), 40px (full-area loaders). Use the brand primary color for the active arc; keep the track in a light neutral.

Live Demo

Spinner variants

Circular border

Bouncing dots

Pulsing bars

Large ring

Spinners signal activity — use when duration is unknown; prefer skeletons for content areas.

Usage

✓ Good usage

A 24px spinner appearing inside a "Save" button while a form submits, replacing the label with "Saving…" — confirming the action is processing.

✗ Bad usage

A full-page spinner for a dropdown that loads 5 options in 80ms — the flash of spinner is more jarring than the perceived wait.

Common mistakes

AI Prompt Example

Copy this into Claude, Cursor, Bolt, or v0.

Replace loading states in this component with accessible spinners. Show a 24px circular spinner inside buttons during async operations, a 40px spinner centered in the content area for page-level loads. Always pair with aria-label="Loading" and appear after a 100ms delay.