Actual CSS

Card

Flexible content container with optional header, body, and footer regions, plus full-bleed children.

Class reference

ClassKindDescription
.cardComponentNeutral raised surface for grouped content.
.raisedVariantElevated surface with a soft shadow.
.subtleVariantLower contrast against the page surface.
.surfaceVariantThe page surface; intent in the text only.
.invertedSurface modifierInverse surface treatment.
.compactDensityTighter 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

Coastal cliffs at dusk

A short caption that wraps across a few lines. The image bleeds to the card edges.

Photo
<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 .bleed child reach the card edge. .compact lowers it.
  • --card-gap — space between direct children of a bare card. A composed layout primitive owns its own gap instead.
Actual CSS

Search documentation