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
shimmerkeyframe defined in globals.css withprefers-reduced-motionhandling. - Background gradient:
from-muted via-muted/50 to-mutedwithbg-[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>