Card
Displays a card with header, content and footer. Four sizes, plus mail, message and call variants.
Playground
<Card>
<CardHeader>
<CardTitle>Welcome back, Sally</CardTitle>
<CardDescription>Three tasks are due today.</CardDescription>
<CardAction>
<Button variant="ghost" size="icon-sm">
<MoreHorizontalIcon />
</Button>
</CardAction>
</CardHeader>
<CardContent>
<p className="text-sm text-muted-foreground">
Cards group related content and actions into a single surface.
</p>
</CardContent>
</Card>Preview
The default variant renders a rounded bg-card surface. CardHeader lays out CardTitle and CardDescription on a grid; CardContent holds the body.
<Card>
<CardHeader>
<CardTitle>Welcome back, Sally</CardTitle>
<CardDescription>
Pick up where you left off – three tasks are due today.
</CardDescription>
</CardHeader>
<CardContent>
<p className="text-sm text-muted-foreground">
Cards group related content and actions into a single surface.
</p>
</CardContent>
</Card>Installation
npx shadcn@latest add https://espresso-base-ui.vercel.app/r/card.jsonUsage
import {
Card,
CardAction,
CardContent,
CardDescription,
CardFooter,
CardHeader,
CardTitle,
} from "@/components/ui/card"<Card>
<CardHeader>
<CardTitle>Title</CardTitle>
<CardDescription>Description</CardDescription>
</CardHeader>
<CardContent>Content</CardContent>
<CardFooter>Footer</CardFooter>
</Card>Variants
Beyond default, three compact variants target common feeds: mail and call are tighter bg-card rows, while message sits on a bg-input surface for chat bubbles. Their content is free-form – the header/content parts are optional.
<Card variant="message" className="inline-block self-start">
<p className="text-sm">
<span className="font-medium text-foreground">@Sandra Bass</span>,
Great teamwork, everyone!
</p>
</Card>
<Card variant="call">
<div className="flex items-center gap-3">
<div className="flex size-8 items-center justify-center rounded-full bg-destructive/10 text-destructive">
<PhoneIncomingIcon className="size-3.5" />
</div>
<div className="flex flex-1 flex-col">
<p className="text-sm font-medium text-foreground">Inbound Call</p>
<p className="text-sm text-destructive">Missed call</p>
</div>
<span className="text-xs text-muted-foreground">14 May</span>
</div>
</Card>Sizes
size scales gap, padding and title typography together across sm, md, lg and xl – the parts read the size from the root via group data attributes, so nothing else changes in your markup.
<Card size="sm">
<CardHeader>
<CardDescription>Revenue</CardDescription>
<CardTitle className="text-2xl">$12,430</CardTitle>
</CardHeader>
<CardContent>
<span className="text-xs text-success-foreground">+8.2% this week</span>
</CardContent>
</Card>API reference
Card is a compound component of plain divs – every part accepts className and standard div props. Only the root takes configuration; the parts read size and variant from it through group data attributes.
Card
| Prop | Type | Default | Description |
|---|---|---|---|
| variant | "default" | "mail" | "message" | "call" | "default" | Surface style – the padded default card, or the compact mail / message / call rows. |
| size | "sm" | "md" | "lg" | "xl" | "md" | Scales the internal gap, horizontal padding and CardTitle type size in the default variant. |
| Component | Description |
|---|---|
| CardHeader | Grid header (data-slot="card-header"). Grows a second column when a CardAction is present and a second row for CardDescription. |
| CardTitle | Heading line (data-slot="card-title"). Sizes with the card: text-sm (sm) up to text-xl (xl). |
| CardDescription | Muted supporting copy under the title (data-slot="card-description"). |
| CardAction | Top-right header slot (data-slot="card-action") for icon buttons or menus – spans both header rows and aligns to the end. |
| CardContent | Main body (data-slot="card-content") with size-aware horizontal padding. |
| CardFooter | Bottom row (data-slot="card-footer"). Its presence removes the card's own bottom padding. |
Styling hooks
The root exposes data-slot="card", data-size and data-variant for CSS targeting. A first-child img automatically loses the card's top padding and gains rounded top corners – handy for cover images. The cardVariants cva helper is exported for building custom card surfaces:
import { cardVariants } from "@/components/ui/card"
<div className={cn(cardVariants({ variant: "message" }))}>
...
</div>