skrewww

Feedback

Skeleton

Skeleton is temporary placeholder shapes that preserve layout while known content is loading.

Shape (Text/Circle/Rectangle) — 3 variants

betaReact AvailableFigma AvailableDocs Partial
React last updated
2026-07-11
Documentation last updated
2026-06-01
Accessibility target
WCAG 2.2 AA (target)
Version
0.3.0-beta

Known open questions

  • Composite skeleton layouts remain documentation examples until Figma confirms reusable list-item presets.

Live preview

Placeholder shapes that preserve layout while content loads.

Text / Circle / Rectangle

Loading container

Loading card content

Skeleton shapes are aria-hidden. The loading region uses aria-busy and screen-reader loading text. Shimmer animation respects prefers-reduced-motion.

Purpose

A placeholder shape mimicking the layout of content that hasn't loaded yet, reducing perceived load time and layout shift.

Anatomy

Skeleton = aria-hidden placeholder shape. SkeletonLoading wraps busy region + screen-reader loading label.

Variants and states

text · circle · rectangle

When to use

Any content area with a known layout shape whose real content takes a moment to load.

When not to use

Content with a genuinely unpredictable final shape/size.

Accessibility

aria-busy="true" on the container while loading; skeleton shapes themselves aria-hidden.

Keyboard behavior

Not interactive.

Common mistakes

Using a skeleton whose shape doesn't reasonably match the real content's eventual layout.

Properties

Shape as variants — composed together in a real "Skeleton List Item" example.

What is the difference between Skeleton and Spinner?

Skeleton preserves layout for known content shapes. Spinner signals activity without mimicking final layout.

Is Skeleton announced by screen readers?

Individual skeleton shapes are hidden. Provide loading text at the container level with aria-busy.

Tokens used

color/neutral/300

Component API

PropTypeDefaultDescription
shape"text" | "circle" | "rectangle""text"Placeholder geometry.
widthstring | numberCustom width.
heightstring | numberCustom height.

React example

Copy React example
import { Skeleton, SkeletonLoading } from "@/components/ui/Skeleton";

export function Example() {
  return (
    <SkeletonLoading
      loading
      loadingLabel="Loading profile"
      skeleton={
        <div style={{ display: "grid", gap: "0.5rem" }}>
          <Skeleton shape="circle" />
          <Skeleton shape="text" width="80%" />
          <Skeleton shape="text" width="60%" />
        </div>
      }
    >
      <p>Loaded content</p>
    </SkeletonLoading>
  );
}