Card

A flexible content container with body, optional header and footer, and image regions.

Basic

A card with just .card__body.

This is some text within a card body.
<div class="card" style="width: 18rem;">
  <div class="card__body">
    This is some text within a card body.
  </div>
</div>

.card__title sits at a fixed font size regardless of the heading tag you pick. .card__subtitle reads --st-muted-foreground so the muted treatment is baked in and no utility is needed.

Card title
Card subtitle

Some quick example text to build on the card title and make up the bulk of the card's content.

Card link Another link
<div class="card" style="width: 18rem;">
  <div class="card__body">
    <h5 class="card__title">Card title</h5>
    <h6 class="card__subtitle">Card subtitle</h6>
    <p class="card__text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
    <a href="#" class="card__link">Card link</a>
    <a href="#" class="card__link">Another link</a>
  </div>
</div>

Images

.card__image is position-aware. As the first child it rounds its top corners to the card's outer radius; as the last child it rounds the bottom. Wrap content in .card__overlay to sit it over the image.

Mountain landscape
Image top

A wider card with supporting text below.

Forest path
Image overlay

A wider card with supporting text below as a natural lead-in.

<div class="demo-row demo-row--top demo-row--gap-md">
  <div class="card" style="width: 18rem;">
    <img src="https://images.unsplash.com/photo-1505740420928-5e560c06d30e?auto=format&fit=crop&w=900&q=70" class="card__image" alt="Mountain landscape" />
    <div class="card__body">
      <h5 class="card__title">Image top</h5>
      <p class="card__text">A wider card with supporting text below.</p>
    </div>
  </div>
  <div class="card" style="width: 18rem;">
    <img src="https://images.unsplash.com/photo-1503264116251-35a269479413?auto=format&fit=crop&w=900&q=60" class="card__image" alt="Forest path" />
    <div class="card__overlay">
      <h5 class="card__title">Image overlay</h5>
      <p class="card__text">A wider card with supporting text below as a natural lead-in.</p>
    </div>
  </div>
</div>

The default header is transparent and inherits the card body background. The footer sits on --st-surface-2 so the body and footer split reads without a heavy border.

Featured
Special title treatment

With supporting text below as a natural lead-in to additional content.

<div class="card" style="width: 22rem;">
  <div class="card__header">
    Featured
    <button type="button" class="btn btn--neutral btn--sm ms-auto">Action</button>
  </div>
  <div class="card__body">
    <h5 class="card__title">Special title treatment</h5>
    <p class="card__text">With supporting text below as a natural lead-in to additional content.</p>
    <button type="button" class="btn btn--primary">Go somewhere</button>
  </div>
  <div class="card__footer">
    <span class="fs-2 text-muted-foreground">2 days ago</span>
  </div>
</div>

Alternate header

Opt the header onto --st-surface-2 to mirror the footer's contrast. Composes with .card__header.

Default header

Header inherits the card body background.

Alt header

Header sits on --st-surface-2.

<div class="demo-row demo-row--top demo-row--gap-md">
  <div class="card" style="width: 18rem;">
    <div class="card__header">Default header</div>
    <div class="card__body">
      <p class="card__text">Header inherits the card body background.</p>
    </div>
  </div>
  <div class="card" style="width: 18rem;">
    <div class="card__header card__header--alt">Alt header</div>
    <div class="card__body">
      <p class="card__text">Header sits on <code>--st-surface-2</code>.</p>
    </div>
  </div>
</div>

Flat

Cards carry a one-pixel border by default so they read as cards with or without elevation. .card--flat drops the shadow when the card should read as a frame rather than a raised surface.

Default

Border and shadow elevation.

Flat

Border, no shadow.

<div class="demo-row demo-row--top demo-row--gap-md">
  <div class="card" style="width: 18rem;">
    <div class="card__body">
      <h5 class="card__title">Default</h5>
      <p class="card__text">Border and shadow elevation.</p>
    </div>
  </div>
  <div class="card card--flat" style="width: 18rem;">
    <div class="card__body">
      <h5 class="card__title">Flat</h5>
      <p class="card__text">Border, no shadow.</p>
    </div>
  </div>
</div>

Customization

Six variables retune .card without touching component CSS. Override on .card itself, on a parent scope, or on :root. The cascade scopes the change.

Variable Default Use
--card-radius var(--st-radius) Corner radius (per-card override via --st-card-radius)
--card-padding calc(1.25rem * var(--st-density)) Padding for header, body, and footer
--card-shadow var(--st-shadow) Drop shadow; .card--flat sets it to none
--card-bg var(--st-surface) Background
--card-color var(--st-foreground) Text color
--card-border 1px solid var(--st-border) Full border shorthand (width, style, color)