Show a spinner only when the wait is noticeable, typically longer than one second. If progress can be measured, prefer a progress bar instead.
When to use
Use spinners when
- The system is actively loading, submitting, or processing
- The wait is long enough that users may wonder whether anything is happening
- The duration is unknown or cannot be expressed reliably as a percentage
- You need compact feedback inside a card, panel, dialog, or page section
Do not use spinners when
- The task finishes almost instantly and no feedback is needed
- Progress can be measured precisely and should be communicated with a progress bar
- Several unrelated areas on the same page would spin at once and compete for attention
- The animation would be decorative rather than meaningful status feedback
Patterns
No label
Use a spinner without text only when the surrounding UI already makes the loading context obvious.
Label below
A strong default for standalone loading states because the message adds context without widening the layout.
Inline label
Use
text-position="right" or text-position="left" when the spinner needs to fit into a horizontal layout.Label above
Useful when the message should appear first in the reading order or fit a stacked composition.
Size variants
Match the spinner size to the container:
small for tight spaces, medium for most cases, large for prominent loading areas.Custom icon
Override the default loader using the
icon slot when you need a different branded or contextual treatment.Anatomy
| Part | Element | Description |
|---|---|---|
| 1 | Spinner icon | The animated circular loader that signals ongoing activity |
| 2 | Progress | The emphasized segment that creates the motion cue and sense of rotation |
| 3 | Label | Optional text that clarifies what is loading, submitting, or processing |
Design guidelines
Choose the spinner treatment that best explains the waiting state without adding noise.Decide whether text is needed
Omit the label only when nearby UI already explains what is loading. Otherwise, add a short task-oriented message.
Choose the position
Use
below as the default for standalone loading states. Use left or right when the spinner needs to fit into a horizontal composition.If you replace the default loader with the
icon slot, you are also replacing the built-in loading status element. Make sure the surrounding UI still communicates that work is in progress.Usage
Default
Use the default spinner when the surrounding UI already makes the loading context obvious and you do not need a custom size or icon.Options
Small
Use the small spinner when space is limited and the loading state belongs to a compact surface.Large
Usesize="large" for prominent loading states such as page-level waits, major panels, or longer-running tasks that need stronger visual emphasis.
With label
Usetext-position to control where the loading message appears relative to the spinner icon.
Custom icon
Use theicon slot when you need a different spinner icon treatment. Make sure the surrounding context still communicates that work is in progress.
Best practices
DoKeep the message short and specific, such as “Loading invoices” or “Submitting form.”
Don’tDo not use a spinner when the system can show real progress or an immediate result instead.
DoMatch the size to the surface:
small for compact containers, medium for standard sections, and large for prominent loading states.Don’tDo not place multiple unrelated spinners on the same page unless each one represents a clearly separate loading region.
DoAdd a visible label when the spinner appears away from the action that triggered it, or when the wait may last several seconds.
Don’tDo not use a spinner as a page-level blocker for instant operations. It creates unnecessary friction.
DoUse
text-position="below" for standalone loading states where vertical layout is natural.Don’tDo not omit a label in contexts where the surrounding UI does not already make the loading operation obvious.
Accessibility
- Built-in loading indicator — the default spinner includes a status element with an accessible loading label that assistive technology can announce. When
textPositionis set to any value other than"none", the visible label text is also available to screen readers. If you replace the default loader with theiconslot, test that the loading state is still communicated clearly in context. - Use meaningful status text when needed: add a short visible label such as “Loading results…” when the spinner appears away from the triggering action or when the wait may last several seconds.
- Keep the message task-oriented: choose labels that describe the current action, such as “Syncing changes” or “Submitting form”, instead of generic filler.
- Be careful with motion changes: setting
animation={false}can make an active process look stalled, so only stop the animation when another clear status treatment explains that work is still ongoing. - Avoid competing announcements: too many independent loading indicators can create noise for screen reader users and make it harder to understand which region is updating.
API reference
Properties
| Property | Attribute | Description | Type | Default |
|---|---|---|---|---|
animation | animation | If false, the animation on the icon element will be stopped | boolean | true |
size | size | Defines the size of the icon element displayed | "small" | "medium" | "large" | "medium" |
textPosition | text-position | Defines the position of the label text | "none" | "left" | "right" | "above" | "below" | "none" |
Slots
| Slot | Description |
|---|---|
| (default) | The label or loading message content |
icon | A custom icon that replaces the default spinner loader |
Shadow parts
| Part | Description |
|---|---|
base | The wrapper container used under the hood |
icon | The <svg> icon element used to spin/animate |
custom-icon | The <span> element that wraps slotted custom icon content |
text | The <span> element that renders the label text |
CSS custom properties
Resources
Interactive playground
Explore spinner sizes, label positions, and custom icon usage in Storybook.
Source code
Browse the component implementation, styles, and tests on GitHub.