Skeleton

Holds the place of content that is loading, in the shape it will take.

Examples

Recent activity loading

Loading recent activity

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'
className
string

Tokens

3 tokens
--surface-2
#efeeea
--radius-sm
6px
--radius-panel
16px

Install

For your coding agent

GitHub

Please star me pookie

141

A new design system every week

Leave your email before you copy the prompt.