Skeleton
A placeholder that mirrors content while it loads.
Bone is the skeleton primitive — a single neutral block. Compose bones into
the shape of the content that is loading so the layout does not jump when the
real data arrives. Reach for it over a spinner when the incoming content has a
predictable structure.
<Bone height={12} />
<Bone height={12} width={160} />
<div className="flex items-center gap-2">
<Bone height={32} circle />
<div className="flex-1">
<Bone height={12} />
</div>
</div>Each bone takes a height and an optional width — omit width to fill the
container. Pass circle for an avatar or icon placeholder; it uses height
for both dimensions and renders a full circle.
A bone never shrinks, and one without a width has no intrinsic size, so in a
flex row it collapses to nothing. Wrap it in a flex-1 element, as above, or
give it an explicit width.
When to use
Use Bone to stand in for content with a predictable structure while it
loads, so the layout does not jump when the data arrives.
Use something else when:
To make a skeleton read as actively loading, layer a Shimmer Overlay on it.
Usage
Do
Match the bones to the real content's dimensions and spacing, so the swap-in is invisible rather than a reflow.
Don't
Fill a screen with dozens of bones. A few that stand in for the primary content read as loading; a full page of them reads as a glitch.
Props
| Prop | Type | Default |
|---|---|---|
heightrequiredHeight in pixels. A `circle` uses it for both dimensions. | Typenumber | Default— |
circleRender a full circle, `height` wide and `height` tall. | Typeboolean | Default— |
radiusCorner radius in pixels. Ignored when `circle` is set. | Typenumber | Default6 |
widthWidth in pixels or any CSS length. Omit to fill the container. | Typestring | number | Default— |
Bone also forwards any div props, such as className or data-testid, to
its root, and its own classes are kept alongside yours.
Accessibility
A bone is a decorative div with no text or role, so it is skipped by screen
readers. Give the loading region a status — for example role="status" with a
"Loading" label — so non-visual users learn the content is on its way.
Each bone sweeps a soft highlight across itself on a 1.6s loop, from
@base-org/bds-web/styles.css. The sweep stops when the reader prefers reduced
motion, leaving a still block.