Skeleton

A shimmer placeholder animation for content that is still loading. Mirrors the shape and dimensions of the real content to reduce layout shift and set user expectations.

Anatomy

A single <Skeleton> div with data-slot="skeleton". The shimmer effect uses a horizontal gradient animation at bg-[length:200%_100%] on an infinite shimmer keyframe. Shape and size are entirely controlled by className.

data-slot="skeleton"shimmer keyframerounded-md default

Examples

Compose multiple skeletons to match your real content layout exactly.

Avatar

Text block

Card

List rows

Design Guidelines

Do

  • Mirror real content shapes. Match the exact dimensions and border-radius of the element being replaced to prevent layout shift on load.
  • Use for determinate loading. Skeleton is best when content will arrive — it tells users what is coming, not just that something is happening.
  • Compose multiple instances. Combine several skeletons to replicate a full section or card layout.

Don't

  • Don't use for indeterminate waits. If the content may never arrive or takes an unknown time, use Spinner instead.
  • Don't animate indefinitely. If loading exceeds ~5 seconds, switch to an error state or a Spinner with a timeout message.
  • Don't add ARIA roles. Skeleton is purely decorative — screen readers should rely on live regions for loading announcements, not the skeleton itself.

Developer Reference

Accessibility

  • data-slot="skeleton" is purely decorative — no ARIA role needed on the element itself.
  • Use an aria-liveregion elsewhere to announce when loading completes (e.g., "Content loaded").
  • Animation uses the shimmer keyframe defined in globals.css with prefers-reduced-motion handling.
  • Background gradient: from-muted via-muted/50 to-muted with bg-[length:200%_100%].

Usage

import { Skeleton } from "@/components/ui/skeleton"

// Single line
<Skeleton className="h-4 w-48" />

// Avatar with text
<div className="flex items-center gap-3">
  <Skeleton className="size-10 rounded-full" />
  <div className="space-y-1.5">
    <Skeleton className="h-3 w-24" />
    <Skeleton className="h-3 w-16" />
  </div>
</div>

// Card placeholder
<div className="space-y-3">
  <Skeleton className="h-32 w-full rounded-lg" />
  <Skeleton className="h-4 w-3/4" />
  <Skeleton className="h-3 w-1/2" />
</div>