Home / Primitives / Skeleton

Skeleton

A shimmering placeholder shaped like the content it stands in for. Use whenever a response takes longer than 300 ms — the operator stays oriented because the layout has already settled.

Stable .skeleton 4 base shapes

Shapes

Four primitives — text line, circle, rectangle, and card. Compose them to mirror the real layout.

Text lines
12 px · varying widths
Circle
Avatar placeholder
Rectangle
Image · chart · thumb
Card
KPI · stat-card placeholder

Table placeholder

Mirrors the row count and column widths so the page doesn't jump when data lands.

ReceiptTillCashierTotal
Loading receipts list

List row composition

Avatar + two text rows. Mirror the real row's vertical rhythm.

Customers list — loading

Parts

PropertyValueNotes
filllinear-gradient muted → sunken → mutedAnimated 1.4 s loop
radius6 px default9999 for circles · 10 px for cards
text height10 / 12 / 14 pxMatch the real type scale
animationcor-skel · 1.4 s ease-in-outHonours prefers-reduced-motion
hold timeShow after 300 msSkip if response is faster

Do & don't

Do

Mirror the real layout — same row count, same column widths. The page should not reflow when data arrives.

Don't

Use a single spinner for content over 200 px tall. The operator loses orientation.

Do

Vary line widths (100 % / 80 % / 60 %) so the placeholder reads as text, not as a brick.

Don't

Show a skeleton for under 300 ms. The flash distracts more than it helps.

Code

<!-- Text lines -->
<div class="skeleton" style="height: 12px; width: 80%;"></div>

<!-- Circle (avatar) -->
<div class="skeleton" style="height: 36px; width: 36px; border-radius: 9999px;"></div>

<!-- Card -->
<div class="skeleton" style="height: 140px; border-radius: 10px;"></div>

Related

For indeterminate spinners under 300 ms, see Spinner. For the loading/error/empty triad, see Empty & loading flows.