Single source of colour, spacing and type for the design system.
Card
Also called tile, panel, content card
A bounded surface grouping the information and actions belonging to one item.
Example
Stretched link
One link, and the button is its sibling rather than its child. Pressing Star records one event; clicking anywhere else in the card follows the link.
Whole card as a link
design-tokensSingle source of colour, spacing and type for the design system.Press Star here and both handlers run — the button first, then the link it is nested inside. The user asked for one thing and got two.
Events fired — in the order they ran
Press Star in either card.
When to use it
- Several items of the same kind sit side by side and each needs its own boundary — products, repositories, articles.
- One item carries mixed content: a title, a summary, some metadata, maybe an action.
- The set is browsed by scanning rather than read in order.
When not to
- The items are rows of the same fields. That is a table, and cards make columns impossible to compare.
- There is only one item on the page. A card around the whole page is a border, not a component.
- The card would hold a single number. That is a stat tile, and a card's padding and chrome only get in its way.
Trade-offs
- The boundary does the grouping, so no heading level or separator has to.
- Works at any width, which makes it the least painful thing to make responsive.
- Each card can carry its own actions without ambiguity about what they act on.
- Borders and padding cost space — a list of twenty cards is far taller than twenty rows.
- Comparing across cards is hard, because values are not aligned in columns.
- The clickable-card problem: whole-card links and inner controls fight each other, and the naive version breaks both.
Accessibility
What this pattern needs in order to work for everyone.
- Keyboard
- A clickable card must be reachable by Tab and activate on Enter — which a `<div onClick>` does not.
- Give it exactly one tab stop for the destination, plus one per real action. A card with six focusable elements is six stops on the way to the next card.
- The focus ring belongs on the whole card, not on the invisible link inside it, or keyboard users cannot see where they are.
- Roles and state
- Do not nest interactive elements. A `<button>` inside an `<a>` is invalid HTML, and a link inside a link is silently rewritten by the browser's parser.
- The stretched-link pattern solves it: the title is a real `<a>`, and a pseudo-element on it covers the card. Other controls sit above it with `position: relative`. One link, one name, buttons still clickable.
- The card's accessible name comes from that link, so the title must be enough on its own — “Read more” tells a screen reader user nothing.
- A decorative image in a card takes `alt=""`; the title already names the item.
- Focus
- Focus follows the visual card. If the card opens something in place, move focus to what opened; if it navigates, let the destination take over.
In the wild
- GitHub repository list — The repo name is the link and stretches over the row; stars and topic tags stay separately clickable.
- Airbnb listings — Whole-card link with the favourite button layered above it — the classic case for the pattern.