Cards
Card — a container of related content + actions, typically clickable as a whole. Material parity (`/components/cards`). 3 variants (elevated, filled, outlined), uniform anatomy, and rules for composition with images, lists, and feeds.
Spec — Cards
Facet *isual*do Koder Design. Material parity: https://m3.material.io/components/cards.
3 card variants
| Variant | Visual | Use |
|---|---|---|
| *levated* | Surface bg + shadow level 1 | Default — slight depth, draws attention |
| *illed* | Surface-variant bg + no shadow | Less emphasis; for embedded cards within a denser context |
| *utlined* | Transparent bg + 1px accent border | High structure, low visual weight (forms with grouped fields) |
Anatomy
┌──────────────────────────────┐
│ [Optional media] │ ← image / video / illustration
│ │
│ Title (title-large) │
│ Subtitle (body-medium muted)│
│ │
│ Body content │
│ │
│ [Action 1] [Action 2] │ ← optional actions
└──────────────────────────────┘- *ontainer* radius
md, padding 1624 px - *edia*(optional): full-width image, aspect 16:9 default
- *itle*
title-large(22/28, weight 600) - *ubtitle*
body-medium(14/20) intext-muted - *ody*
body-medium - *ctions* button row, right-aligned (or left in RTL)
R1 — Card density
| Density | Padding | Use |
|---|---|---|
| Comfortable | 24 px | Default — feeds, dashboards |
| Compact | 16 px | Dense lists (table cards, multi-column grids) |
| Spacious | 32 px | Hero cards (single card per fold) |
Density follows themes/ui-style.kmd preset's density token; can be explicitly overridden per card via class modifier.
R2 — Clickable card
Most cards are clickable as a whole (navigate to detail).
- Entire card surface is the hit area
- Hover state: subtle elevation boost (+1 level) OR background tint
- Focus ring: 2 px on outer container (per
interaction/states.kmd) role="link"if it navigates;role="button"if it triggers an action- Inner buttons are stop-propagation: clicking them doesn't trigger
the card's main action
- Cursor: pointer on whole card
R3 — Compositions
Feed item card
Used in vertical scrollable feeds (per canonical-layouts.kmd L1).
- Compact density
- Title + subtitle + 1-3 lines of body
- Optional avatar (40 px) + author name + timestamp
- Click navigates to detail
Product card
- Elevated variant
- Hero image (16:9 or 1:1)
- Title + price + rating
- "Add to cart" or similar primary action
- Hover: shadow boost + slight scale (1.02)
List-detail card
- Outlined or Filled variant
- Selected state: accent-tinted bg + accent border (1.5 px)
- Used in list-detail layout (per L2)
Stats card (dashboard)
- Outlined variant
- Large numeric value (
headline-large) - Label (
title-smallmuted) - Optional sparkline / mini-chart
R4 — Cards within cards
*nti-pattern.*A card MUST NOT contain another card. If nesting feels needed, the inner content should be a listitem, expansionpanel, or embedded section — not a card.
Exception: a card containing one image-card preview (e.g., a tweet embed inside a notification card) — allowed because the inner is a quoted/embedded artifact, not a peer container.
R5 — Media handling
- Aspect ratio: 16:9 (default), 1:1 (square avatar/product), 4:3 (legacy)
- Loading: skeleton placeholder matches final aspect (no layout shift)
- Failure: fallback to
surface-variantbg + icon - Alt text:
altattribute REQUIRED for non-decorative images - Lazy-loading:
loading="lazy"for cards below the fold
R6 — Per-preset variation
| Preset | Variant emphasis |
|---|---|
material3 |
Elevated default (subtle shadow) |
material2 |
Stronger shadows, sharper corners |
windows_11 |
Mica backdrop blur on Elevated |
windows_95 |
3D bevel border instead of shadow; sharp corners |
glassmorphism |
Translucent + backdrop blur |
brutalist |
Outlined only (no shadows, thick border) |
neumorphism |
Soft inverse shadow (looks "pressed into" surface) |
dieter_rams |
Outlined default; minimal ornament |
R7 — Accessibility
- Card title is a heading (
<h2>-<h4>depending on page level) - Clickable card focus ring on outer container only (not on title)
- Inner buttons reachable by Tab (separately from card focus)
- Reading order matches visual order (DOM = visual)
R8 — Forbidden patterns
- ❌ Card without title (just a body of text) — use a
<section>instead - ❌ Multiple primary actions in card actions row (1 primary, N secondary)
- ❌ Card with no border + no shadow + no bg variation (use a plain
<div>) - ❌ Animations that change card height on hover (causes feed shift)
Cross-link
app-layout/canonical-layouts.kmd— feed (L1) uses cardsthemes/elevation.kmd— Elevated variant level 1 defaultthemes/shape.kmd— radius-md containerinteraction/states.kmd— hover/focus per card typefoundations/elements.kmd— Container family