Cmpnts

Menu

Molecules

Card

A surface with named parts, such as a header, a body and a footer, for one thing a person can read, compare or act on.


Shade borders

Ferns, hostas and hellebores under trees.

Code
HTML
<article class="card">
  <header class="card__header"><h2 class="card__title heading">Shade borders</h2></header>
  <div class="card__body"><p class="text">Ferns, hostas and hellebores under trees.</p></div>
  <footer class="card__footer"><a href="#when-to-use" class="link small-text">Plant list</a></footer>
</article>

Why it exists

A Card says that what’s inside is one thing, which stands alone and can be compared with others. That is the only reason to draw a box. Content comes first, so most sections of a page need space and a heading, not a Card.

The Card draws a frame and lays out its parts, and nothing else. Type comes from the text atoms, so a Card’s title is the same heading as any other, and whatever goes in the body is ordinary content.

Because it is only a surface with parts, Dialog and Popover are built on it. Learn its parts once and you know the inside of all three.

When to use

  • For one thing among several: an article in a list, a product, a setting, a dashboard panel. Each Card stands alone and can be compared with the others.
  • Not for every box on a page. Sections of one page are separated by space and headings, not Cards. A Card inside a Card usually means one of them should be space instead.
  • Not for a message (a Banner) or a modal (a Dialog, which holds a Card).

Rules

  • Structure: parts (__thumb, __header, __band, __body, __footer) are direct children of .card, and each pads itself. .card__content wraps parts only beside a __thumb in a row Card (--card-dir: row).

  • Typography: use text atoms on titles and body copy (.heading, .text, .small-text). The Card hooks never set type.

  • Intent marks a Card’s state: live, selected, current, at risk. The whole border takes the intent colour and a ring outside it doubles the edge, so it reads at a glance; the ring doesn’t take space, so a Card changing state doesn’t move its content. Wherever the Card has a shadow (--strong, a linked Card on hover) the shadow takes the intent colour too, the raised stack mixed 75% towards transparent (--card-intent-shadow-transparency); a default Card gains no shadow, and increased contrast drops it as usual. It draws the border at any prominence or chrome (.card--flat.card--accent keeps square corners). It is never colour alone (WCAG 1.4.1): the Card says the state in words too, usually with a status of the same intent in the header. Intent is a state, not decoration, so it has no responsive versions.

  • Linked Card: a .link.link--plain.link--stretched in the title makes the whole Card the target. The focus ring is drawn on the Card’s perimeter and other controls are lifted above the Link.

  • Scrolling: .card__body--scrollable scrolls the body between a pinned header and footer (the Card fills a definite container height). .card--scrollable scrolls the whole Card. Make the scroll region focusable (tabindex="0") and name it.

  • Loading: a Card with aria-busy="true", a role="status" message and Skeleton shapes.

Linked Card with Media

Article headline

Supporting subtitle

Short summary describing the content.

Code
HTML
<article class="card">
  <div class="card__thumb">
    <img src="/examples/cover.svg" alt="" loading="lazy" />
  </div>
  <header class="card__header">
    <hgroup class="card__hgroup">
      <h3 class="card__title heading">
        <a href="/articles/my-post" class="link link--plain link--stretched">Article headline</a>
      </h3>
      <p class="card__subtitle small-text">Supporting subtitle</p>
    </hgroup>
  </header>
  <div class="card__body">
    <p class="text">Short summary describing the content.</p>
  </div>
  <footer class="card__footer">
    <time class="small-text text-muted" datetime="2026-09-30">30 September 2026</time>
  </footer>
</article>

Status and Action in the header

Security settings

Two-factor authentication

Active

Manage passkeys, hardware tokens and two-factor authentication.

Updated 2 days ago
Code
HTML
<article class="card">
  <header class="card__header">
    <hgroup class="card__hgroup">
      <h3 class="card__title heading">Security settings</h3>
      <p class="card__subtitle small-text">Two-factor authentication</p>
    </hgroup>
    <span class="status status--success"><span class="status__text">Active</span></span>
  </header>
  <div class="card__body">
    <p class="text">Manage passkeys, hardware tokens and two-factor authentication.</p>
  </div>
  <footer class="card__footer">
    <span class="small-text text-muted">Updated 2 days ago</span>
    <button type="button" class="button button--subtle"><span>Configure</span></button>
  </footer>
</article>

The title takes the free space but never shrinks below its longest word. In a narrow Card the Status or action wraps to the next line instead of running over the title. A .truncate title keeps shrinking.

Do and Don’t

DoDon’t
Make the whole Card the Link with one stretched link in the title.Wrap the Card in an <a>, or add a second “Read more” link to the same place.
Say a Card’s state in words (a Status in the header) as well as its intent colour.Mark a Card as live or at risk by its border colour alone.
Give a Card’s image alt="" when the title says what it shows.Repeat the title in the image’s alt.
Use text atoms for the title and body (.heading, .text).Size type with the Card’s own classes or utilities.
Use space and headings to separate sections of one page.Box every section in a Card.

In Storybook

See also

  • Dialog: A modal window on top of the page, for a decision, a short form or a drawer of settings.
  • Popover: A layer anchored to the control that opens it, holding a Card or a Menu.
  • Thumbnail: A small picture of a thing, such as album art, a product shot or a file preview.

Search the docs