Card
Flexible content container with optional header, body, and footer regions, plus full-bleed children.
Class reference
| Class | Kind | Description |
|---|---|---|
.card | Component | Neutral raised surface for grouped content. |
.raised | Variant | Elevated surface with a soft shadow. |
.subtle | Variant | Lower contrast against the page surface. |
.surface | Variant | The page surface; intent in the text only. |
.inverted | Surface modifier | Inverse surface treatment. |
.compact | Density | Tighter padding and compact descendant context. |
.surface is a shared variant: it paints the page surface instead of
--surface-raised and leaves the intent to the text.
.inverted paints --surface-solid and swaps the foreground to --surface,
so it inverts in dark themes instead of always reading as dark. Write it as
class="card inverted", or on any block.
Basic usage
Use semantic elements inside the card. A direct <header> or <footer> is the
card's structural slot. A direct <footer> is anchored to the bottom of the
card when extra block space is available, so prices and actions line up across
equal-height cards. Cards do not own page spacing — compose them with layout
primitives like .grid. A bare card owns the rhythm between its direct
children through --card-gap; applying a layout primitive such as .stack or
.media to the same element gives that primitive control of the layout and
gap.
Understanding Semantic HTML
A quick primer for new contributors
Using the right HTML tags improves both SEO and accessibility. Lean on landmarks and live lists.
- HTML
- Accessibility
- 5 min read
<div style="max-inline-size: 32rem">
<article class="card stack">
<header>
<hgroup>
<h3>Understanding Semantic HTML</h3>
<p class="muted">A quick primer for new contributors</p>
</hgroup>
</header>
<p>Using the right HTML tags improves both SEO and accessibility. Lean on landmarks and live lists.</p>
<ul class="cluster" style="list-style: none; padding: 0; margin: 0; gap: 0.5rem" aria-label="Tags">
<li><span class="badge primary soft secondary">HTML</span></li>
<li><span class="badge soft primary">Accessibility</span></li>
<li><span class="badge outline">5 min read</span></li>
</ul>
<footer>
<time datetime="2026-06-12" class="muted">June 12, 2026</time>
<button type="button" class="btn outline">Read more</button>
</footer>
</article>
</div>
Bleed
Use .bleed on a direct child to escape the card padding — full-width images,
colored headers, or footers.
Coastal cliffs at dusk
A short caption that wraps across a few lines. The image bleeds to the card edges.
<div style="max-inline-size: 32rem">
<article class="card stack">
<img class="bleed" src="https://picsum.photos/seed/actual-css-card/600/300" alt="Coastal cliffs at dusk" />
<header>
<h3>Coastal cliffs at dusk</h3>
</header>
<section class="stack" aria-label="Summary">
<p>A short caption that wraps across a few lines. The image bleeds to the card edges.</p>
</section>
<footer>
<span class="badge primary soft">Photo</span>
<button type="button" class="btn outline">View</button>
</footer>
</article>
</div>
Team
For growing products
$24 / user / month
- Unlimited projects
- Up to 25 seats
- Shared workspaces
- Priority support
<article class="card stack" style="--card-max-inline-size: 24rem">
<header class="bleed stack items-center text-center" style="background: var(--surface-subtle)">
<hgroup>
<h3>Team</h3>
<p class="muted">For growing products</p>
</hgroup>
<p>
<span style="font-size: 2rem; font-weight: var(--font-weight-semibold); line-height: 1">$24</span>
<span class="muted">/ user / month</span>
</p>
</header>
<ul class="stack items-center" style="list-style: none; padding: 0">
<li>Unlimited projects</li>
<li>Up to 25 seats</li>
<li>Shared workspaces</li>
<li>Priority support</li>
</ul>
<footer class="bleed" style="background: var(--surface-subtle); justify-content: center">
<a class="btn primary" href="#">Upgrade</a>
</footer>
</article>
In grids
Cards display nicely in grids with equal-height behavior. Each card in a row
stretches to the row height, and a direct <footer> anchors to the bottom, so
all footers in the row line up regardless of body length.
Components
Buttons, alerts, dialogs — all opt-in.
Layout
Stack, cluster, grid, switcher, sidebar.
Patterns
Actions, nav-list — small structural helpers.
<section class="grid">
<article class="card">
<header>
<h3>Components</h3>
</header>
<p>Buttons, alerts, dialogs — all opt-in.</p>
<footer>
<a class="btn outline" href="#">Browse</a>
</footer>
</article>
<article class="card">
<header>
<h3>Layout</h3>
</header>
<p>Stack, cluster, grid, switcher, sidebar.</p>
<footer>
<a class="btn outline" href="#">Browse</a>
</footer>
</article>
<article class="card">
<header>
<h3>Patterns</h3>
</header>
<p>Actions, nav-list — small structural helpers.</p>
<footer>
<a class="btn outline" href="#">Browse</a>
</footer>
</article>
</section>
Surfaces
.inverted creates a contrasting surface context, not a complete theme island.
On a bare block (<header class="inverted">, <section class="inverted">) it
paints the surface directly; contextual content and transparent treatments such
as .btn.outline, .btn.ghost, and .btn.link follow its foreground.
Apply it directly to a component that consumes the shared --ui-* surface
contract (.card, .navbar, .alert, .badge) to treat that component as the
contrasting surface. A surface-owning component nested inside an inverted block
keeps its own surface and establishes a new context for its descendants. Use a
data-theme island when every component and form control in a subtree must use
another theme.
More specific component states or explicit surface variants still take
precedence: .card.inverted.subtle keeps the .subtle background while the
foreground stays inverted.
.inverted and .subtle are competing surface treatments — do not combine
them. .subtle paints the card's background directly while .inverted swaps
the surface tokens, so .card.subtle.inverted renders a subtle background with
inverted foreground. Treat them as mutually exclusive, like two competing
variants.
.surface is the shared variant on a card: it drops the card to the page
surface instead of --surface-raised, keeps the theme border, and lets an
intent class color the text only. .raised and .subtle are the card-local
treatments on either side of it.
Raised
Elevated surface with a soft shadow.
Subtle
Lower contrast against the page surface.
Surface
The page surface with the theme border.
Inverted
Inverse surface for emphasis. Text inherits the contrasting surface color.
Compact
Tighter padding for dense contexts.
<section class="grid">
<article class="card raised">
<hgroup>
<h3>Raised</h3>
<p class="muted">Elevated surface with a soft shadow.</p>
</hgroup>
</article>
<article class="card subtle">
<hgroup>
<h3>Subtle</h3>
<p class="muted">Lower contrast against the page surface.</p>
</hgroup>
</article>
<article class="card surface">
<hgroup>
<h3>Surface</h3>
<p class="muted">The page surface with the theme border.</p>
</hgroup>
</article>
<article class="card inverted stack">
<hgroup>
<h3>Inverted</h3>
<p>Inverse surface for emphasis. Text inherits the contrasting surface color.</p>
</hgroup>
<button type="button" class="btn">Action</button>
</article>
<article class="card compact">
<hgroup>
<h3>Compact</h3>
<p class="muted">Tighter padding for dense contexts.</p>
</hgroup>
</article>
</section>
CSS hooks
--card-radius— corner radius.--card-max-inline-size— maximum width.--card-pad— inner padding; also drives the negative offsets that let a.bleedchild reach the card edge..compactlowers it.--card-gap— space between direct children of a bare card. A composed layout primitive owns its own gap instead.