Skeleton

A hand-drawn loading placeholder that pulses while content loads.

Overview

A Skeleton is a placeholder that stands in for content while it loads, preserving layout and hinting at the shape of what’s coming. Prefer it over a bare Spinner when you can approximate the final layout (a list row, a card, a paragraph).

Anatomy

A sketchy filled shape (@ghds/sketch-core) in the muted surface colour that gently pulses its opacity. Three variants — rect (default), text (a rounded line), and circle (e.g. an avatar placeholder) — set the default shape, radius, and size; width/height override them.

Variants & States

State Status Notes
Pulsing Implemented Opacity animates between full and dimmed while loading.
Reduced motion Implemented The pulse is suppressed under prefers-reduced-motion; the placeholder is shown static.
Hover / Focus / Disabled Not implemented Skeleton is not interactive.

Usage

Do

  • Match the skeleton to the real content it replaces — same rough size and shape.
  • Compose several (circle + text lines) to mirror a card or list row.
  • Set aria-busy on the region that contains the skeletons so assistive tech knows it is loading.

Don't

  • Don't leave skeletons up indefinitely — swap in real content (or an error state) when the request settles.
  • Don't rely on the skeleton itself for a busy announcement — it is aria-hidden by design.

Accessibility

Content

No content — a Skeleton is a shape only. Use width/height and multiple instances to approximate the incoming layout.

Props API

React@ghds/react

PropTypeDefaultDescription
variant'rect' | 'text' | 'circle''rect'Placeholder shape.
widthnumber | stringWidth (number ⇒ px). Defaults to 100% (diameter for circle).
heightnumber | stringHeight (number ⇒ px). Defaults per variant.
...restHTMLAttributes<HTMLSpanElement>Native <span> attributes pass through.

Web Components@ghds/web-components

PropTypeDefaultDescription
variant'rect' | 'text' | 'circle''rect'Placeholder shape (reflected attribute).
widthstringCSS width. Defaults to 100% (diameter for circle).
heightstringCSS height. Defaults per variant.

React Native@ghds/react-native

PropTypeDefaultDescription
variant'rect' | 'text' | 'circle''rect'Placeholder shape.
widthDimensionValueWidth. Defaults to 100% (diameter for circle).
heightDimensionValueHeight. Defaults per variant.
testIDstringTest handle for queries.

Code examples

// React — @ghds/react
import { Skeleton } from '@ghds/react/skeleton';

<Skeleton variant="circle" />;
<Skeleton variant="text" width="70%" />;
<!-- Web Components — @ghds/web-components -->
<script type="module">
  import '@ghds/web-components/skeleton';
</script>
<gh-skeleton variant="circle"></gh-skeleton>
<gh-skeleton variant="text" width="70%"></gh-skeleton>
// React Native — @ghds/react-native
import { Skeleton } from '@ghds/react-native/skeleton';

<Skeleton variant="text" width="70%" />;

Live Demo

React @ghds/react

Web Components @ghds/web-components