Skeleton
Holds the place of content that is loading, in the shape it will take.
Examples
Shape
textdefault
circle
block
Usage
When to use it
- Use
- A list, card or figure is loading and its shape is known, such as recent activity or a balance.
- Use
- The first load of a screen, so the layout is in place before the words arrive.
- Not for
- A piece of work the person started, such as sending money. Use Button.
- Not for
- Work that runs on its own and has a word for its state. Use Status.
- Not for
- The load failed. Use Error state.
Rules
7 rules
- Never
- Animate a skeleton with a pulse or a sweep; Lime has one looping motion, the spinner. Because a second loop on the page and the spinner stops being the one sign of work.
- Must
- Set aria-busy on the loading region and put one sr-only line in it that says what is loading. Because every Skeleton is aria-hidden, so without the line a screen reader hears nothing load.
- Must
- Match the real content: the same row height, mark size and line count. Because a shorter stand-in pushes the balance and buttons below it down when the data lands.
- Should
- Give lines different widths, as real titles and dates have.
- Should
- Show three to five rows of a list, not a screenful.
- Never
- Put a skeleton in place of a button or a field the person needs; show the control disabled. Because a grey bar takes no focus and has no name, so Send is missing until data lands.
- Never
- Fill a skeleton with lime or a status hue; it is always the grey surface. Because lime marks the next step and status hues mean paid or declined, so a tinted bar reads as one.
Accessibility
3 checks
- Every skeleton is aria-hidden; the region says Loading once, in an sr-only line.
- aria-busy on the region tells a screen reader to wait for the content.
- Nothing moves, so there is nothing to stop under reduced motion.
Edge cases
4 edge cases
- Slow network
- The skeleton stays; after about 10 seconds, say so in the region or show an Error state.
- Fast load
- Show it only if loading takes over 300ms, so it does not flash.
- Dark theme
- The second surface still reads on the dark page.
- Inside a grouped list
- Sits on the warm-grey card one step darker.
API
2 props
shape'text' | 'circle' | 'block'default'text'classNamestring
Tokens
3 tokens
--surface-2- #efeeea
--radius-sm- 6px
--radius-panel- 16px