Browse Components

Skeleton

Reserve space while content loads.

Basic

Reserve space for a short paragraph while it loads.

Loading article…
View Code
HTML
<div class="skeleton-content" aria-busy="true" aria-label="Loading article">
  <span class="sr-only" role="status">
    Loading article…
  </span>
  <div class="skeleton-lines" aria-hidden="true">
    <span class="skeleton skeleton-text" style="--skeleton-width:72%">
    </span>
    <span class="skeleton skeleton-text">
    </span>
    <span class="skeleton skeleton-text" style="--skeleton-width:88%">
    </span>
  </div>
</div>

Profile

Match the avatar size and text alignment of the loaded profile.

Loading profile…
View Code
HTML
<div class="skeleton-content" aria-busy="true" aria-label="Loading profile">
  <span class="sr-only" role="status">
    Loading profile…
  </span>
  <div class="skeleton-profile" aria-hidden="true">
    <span class="skeleton skeleton-circle">
    </span>
    <div class="skeleton-lines">
      <span class="skeleton skeleton-text" style="--skeleton-width:48%">
      </span>
      <span class="skeleton skeleton-text" style="--skeleton-width:72%">
      </span>
    </div>
  </div>
</div>

Card

Keep the media aspect ratio and content spacing stable.

Loading card…
View Code
HTML
<div class="skeleton-content skeleton-card" aria-busy="true" aria-label="Loading card">
  <span class="sr-only" role="status">
    Loading card…
  </span>
  <div class="skeleton skeleton-media" aria-hidden="true">
  </div>
  <div class="skeleton-lines" aria-hidden="true">
    <span
      class="skeleton skeleton-text"
      style="--skeleton-width:60%;--skeleton-height:24px"
    >
    </span>
    <span class="skeleton skeleton-text">
    </span>
    <span class="skeleton skeleton-text" style="--skeleton-width:82%">
    </span>
  </div>
</div>

Without motion

Reduced-motion preferences receive the same static appearance.

Loading article…
View Code
HTML
<div
  class="skeleton-content"
  data-motion="none"
  aria-busy="true"
  aria-label="Loading article"
>
  <span class="sr-only" role="status">
    Loading article…
  </span>
  <div class="skeleton-lines" aria-hidden="true">
    <span class="skeleton skeleton-text" style="--skeleton-width:72%">
    </span>
    <span class="skeleton skeleton-text">
    </span>
    <span class="skeleton skeleton-text" style="--skeleton-width:88%">
    </span>
  </div>
</div>

Right-to-left

Shorter lines align with the reading direction.

Loading profile…
View Code
HTML
<div dir="rtl">
  <div class="skeleton-content" aria-busy="true" aria-label="Loading profile">
    <span class="sr-only" role="status">
      Loading profile…
    </span>
    <div class="skeleton-profile" aria-hidden="true">
      <span class="skeleton skeleton-circle">
      </span>
      <div class="skeleton-lines">
        <span class="skeleton skeleton-text" style="--skeleton-width:48%">
        </span>
        <span class="skeleton skeleton-text" style="--skeleton-width:72%">
        </span>
      </div>
    </div>
  </div>
</div>

Installation

Download these files into the matching paths in your project, or use Create to assemble a kit. Include each dependency once. Do not also load app.css.

Add to your page
<link rel="stylesheet" href="/library/assets/base.css">
<link rel="stylesheet" href="/library/assets/skeleton.css">

9,557 bytes CSS including base · 0 bytes runtime JavaScript

Usage

Loading semantics

Use .skeleton for decorative placeholder shapes, with aria-hidden=true on the shapes or their wrapper. Apply aria-busy=true to the region being loaded and provide one concise status message for the whole region, never one per shape. Use skeleton-text, skeleton-circle and skeleton-media for text, avatars and reserved image space; customize --skeleton-width, --skeleton-height and --skeleton-ratio. Compose skeleton-lines, skeleton-profile and skeleton-card as needed. Match the final content dimensions to avoid layout shifts. The CSS-only pulse uses four shared motion durations; reduced motion and data-motion=none keep shapes static. Replace placeholders with real content and clear aria-busy when loading finishes. Applications own loading, errors and retries; do not leave skeletons indefinitely or use them for empty results. No JavaScript, timers, automatic data fetching, focusable placeholders or simulated completion.

Shape the expected content

Keep placeholder layouts close to the real content. Prefer a spinner for an action with no known layout, and an Empty component when loading succeeds with no results. Skeletons use neutral theme colors rather than brand fills.

Building with AI? The AI Manifest has these notes and the full contract. See the AI Guide.