Content
Card
Group related content in a container: a macOS group box, or an iOS widget-like card.
Storage
412 GB of 1 TB used
Photos and Messages take the most space on this Mac.
Software Update
macOS 26.1 is ready to install.
Family Sharing
Share subscriptions, purchases and location with up to five people.
import { Button } from "macbetter/button"
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "macbetter/card"
export default function Example() {
return (
// Grouped cards sit on the grouped background, the way iOS Settings draws them.
<div
style={{
display: "grid",
gridTemplateColumns: "repeat(auto-fit, minmax(220px, 1fr))",
gap: 16,
width: "100%",
padding: 16,
borderRadius: 16,
background: "var(--mb-bg-grouped)",
}}
>
<Card variant="grouped">
<CardHeader>
<CardTitle>Storage</CardTitle>
<CardDescription>412 GB of 1 TB used</CardDescription>
</CardHeader>
<CardContent>Photos and Messages take the most space on this Mac.</CardContent>
</Card>
<Card variant="elevated">
<CardHeader>
<CardTitle>Software Update</CardTitle>
<CardDescription>macOS 26.1 is ready to install.</CardDescription>
</CardHeader>
<CardFooter>
<Button size="sm" variant="filled">
Update Now
</Button>
</CardFooter>
</Card>
<Card variant="outline">
<CardHeader>
<CardTitle>Family Sharing</CardTitle>
<CardDescription>Share subscriptions, purchases and location with up to five people.</CardDescription>
</CardHeader>
</Card>
</div>
)
}When to use it
Use a card to set a small amount of related content apart from what's around it: a summary with an action, a status, a preview that leads somewhere. On the Mac, a grouped card is the group box that frames related settings.
- Keep a card to one subject. If it needs a scroll bar, it's a page.
- Give it a title, and at most one prominent action in the footer.
- Use a List for rows of settings, not a stack of cards.
Usage
import {
Card,
CardContent,
CardDescription,
CardFooter,
CardHeader,
CardTitle,
} from "macbetter/card"CardTitle is an h3 and CardDescription a paragraph. CardFooter lines its buttons up at the trailing edge.
Variants
grouped, the default: the secondary grouped background. On the Mac it's a faint fill with a hairline edge, which reads on any window. On iOS it's the white (or raised dark) cell color, meant to sit on a grouped background.elevated: a raised surface with a soft shadow, for a card that floats above the page.material: a translucent material that blurs what's behind it, for a card over a photo or a wallpaper. Never put it on another material.outline: a hairline edge and no fill, for a quiet container.
Cupertino
72° Mostly Sunny
High 78° · Low 55°. Clear skies through the evening.
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "macbetter/card"
// A local CSS artwork stands in for a photo, so the material has something to blur.
const sky = {
display: "grid",
placeItems: "center",
width: "100%",
maxWidth: 520,
padding: "40px 24px",
borderRadius: 20,
background:
"radial-gradient(circle at 22% 28%, #ffd27a 0 12%, transparent 13%), radial-gradient(120% 90% at 80% 100%, #2f6fd6, transparent 60%), linear-gradient(160deg, #7cc4ff, #3a7bd5 55%, #f3a46b)",
} as const
export default function Example() {
return (
<div style={sky}>
<Card variant="material" style={{ width: 280 }}>
<CardHeader>
<CardDescription>Cupertino</CardDescription>
<CardTitle>72° Mostly Sunny</CardTitle>
</CardHeader>
<CardContent>High 78° · Low 55°. Clear skies through the evening.</CardContent>
</Card>
</div>
)
}Platform behavior
- macOS. 13-point semibold titles, 16-point padding and a 12-point corner radius, like a group box in System Settings.
- iOS and iPadOS. 17-point semibold titles and a 22-point corner radius, like a widget or an inset grouped cell. A grouped card is white in light appearance, so put it on
--mb-bg-grouped, as Settings does; on a white page useelevatedoroutline. - Corners are continuous where the browser supports
corner-shape, so the curve eases into the straight edge as Apple's do. Elsewhere they're round. - Under Reduce Transparency or Increase Contrast, the material card turns opaque.
Accessibility
- A card is a plain container. It adds no role: its title is a heading, so people using screen readers can find it.
- If the whole card should be pressable, make its title a link or put a button in the footer rather than turning the card into a button around other controls.
- Text on a material card keeps its contrast because the material is mostly opaque; check it over your own imagery.
API
Card
| Prop | Type | Default | Description |
|---|---|---|---|
variant | "grouped" | "elevated" | "material" | "outline" | "grouped" | The card's surface. |
...props | ComponentProps<"div"> | — | Passed to the element. |
CardHeader, CardContent and CardFooter render a div, CardTitle an h3, and CardDescription a p.
CSS variables
| Variable | Meaning |
|---|---|
--mb-card-padding, --mb-card-gap | Padding and the space between parts. |
--mb-card-radius | The corner radius. |
--mb-card-grouped-bg, --mb-card-grouped-edge | The grouped surface and its edge. |