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
<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__contentwraps parts only beside a__thumbin 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--accentkeeps 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--stretchedin 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--scrollablescrolls the body between a pinned header and footer (the Card fills a definite container height)..card--scrollablescrolls the whole Card. Make the scroll region focusable (tabindex="0") and name it. -
Loading: a Card with
aria-busy="true", arole="status"message and Skeleton shapes.
Linked Card with Media
Article headline
Supporting subtitle
Short summary describing the content.
Code
<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
ActiveManage passkeys, hardware tokens and two-factor authentication.
Code
<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
| Do | Don’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. |