Skeleton

Placeholder shapes that hold space while content loads. The shimmer is pure CSS. The skeleton-to-content crossfade uses AnimatePresence with popLayout.

Live demo

Avatar

User avatar

Text — 3 lines

Your recent activity has been summarised below.

3 tasks completed, 1 pending review.

Last updated just now.

Card

User

Alex Morgan

Product Designer · Active now

Why it animates

Content that loads asynchronously needs a placeholder that matches the shape of what's coming. A skeleton that mirrors the real layout reduces perceived shift and makes the wait feel intentional rather than broken.

Usage
import { Skeleton } from '@/components/ui/Skeleton'

<Skeleton shape="avatar" loading={isLoading}>
  <img src={user.avatar} alt={user.name} className="w-10 h-10 rounded-full" />
</Skeleton>

<Skeleton shape="text" lines={3} loading={isLoading}>
  <p>{content}</p>
</Skeleton>

<Skeleton shape="card" loading={isLoading}>
  <UserCard user={user} />
</Skeleton>