Skeleton

The optimistic loading state: structure first, content on arrival.

v1.0.0·Updated Jul 8, 2026 · 10:45
Live Demo — Fully Interactive
Lines mirror the shape of the text to come
Configuration
Shape
Width
Shimmer
<Skeleton variant="line" width="75%" />
Behavior — The Engineering Contract
PropTypeNotes
variantline · circle · boxThe primitive shape
width / heightnumber | stringMatch the real element it stands in for
shimmerbooleanThe sweeping highlight; on by default
countnumberRepeat lines for a text block
reduced-motionDrops the shimmer, keeps the shape

Use a Skeleton when you know the shape of what's loading. For an unmeasurable or shapeless wait use a Loader; for measurable work use Progress.

Anatomy
1ShapeA primitive sized to the real element.
2ShimmerA soft sweep signalling "loading", not stuck.
Do's and Don'ts
✓ Do

Vary line widths so the block reads like real paragraphs.

✕ Don't

Don't make every line full-width. It reads as a solid block.

✓ Do

Mirror the real layout so nothing jumps when content lands.

✕ Don't
Loading…

Don't use a lone spinner where the shape is known. Show structure.

In context: Examples
A · Card

Media cards while the image and title load.

B · List row

Repeated rows for a loading list or table.

C · Text block

Article and detail views before the copy arrives.

Measurements & Tokens
TokenValueRole
--skel-bg#16171BPlaceholder fill
--skel-shimmerrgba(255,255,255,.055)Sweeping highlight
--skel-speed1.4sShimmer period
--skel-line-h11pxDefault line height
--skel-radius5px line · 9px boxCorner per shape
--skel-reducedno shimmerReduced-motion fallback
Code
<div class="o-skel o-skel--line" style="width:40%"></div>
<div class="o-skel o-skel--line"></div>
<div class="o-skel o-skel--line" style="width:78%"></div>

<div class="o-skel o-skel--circle" style="width:40px;height:40px"></div>