Card Component

The `card` component is a responsive, self-contained card element that adapts its layout based on its container size using container queries. It features scoped

Card anatomy keeps content roles explicit

Media, header, content, and footer each own a predictable part of the card.

16 / 9 media
Design systems report

Patterns, adoption, and accessibility findings.

Updated 12 minutes ago

More examples

Each example introduces a different part of the shipped API.

Adaptive cards respond to their container

Resize the preview: media moves beside the body when the card container reaches its layout threshold.

Media
Container-aware card

Its layout changes from stacked to horizontal based on available card width.

Overview

The card component is a responsive, self-contained surface that adapts its layout based on its container size. Its selectors stay component-scoped through explicit card host and part names, and its visual roles are controlled by semantic tokens.

Live card

Hover it, then resize the page to see its container-query layout.

Featured6 min readDesigning with container queries

A card can respond to the space it receives instead of the viewport.

The card supports custom-element, class, and data-* hosts. The same structure can use <card>, .card, or [data-card]; its parts likewise support card-body, .card-body, and [data-card-body].

Key Features

  • Container Queries: Layout adapts to the card’s own width, not viewport
  • Explicit Styling: Selectors target only card hosts and named card parts
  • Responsive Design: Switches from vertical to horizontal layout at 32rem container width
  • Elevation Effects: Hover animations with shadow changes
  • Flexible Content: Supports media, header, content, and footer sections

Structure

The card component consists of several semantic elements:

  • card-media: Image or media content (16:9 aspect ratio by default)
  • card-body: Main content container
  • card-header: Card title (larger, bold text)
  • card-content: Primary content (flexible growth)
  • card-footer: Footer content (smaller, muted text)

Layout Behavior

Narrow Layout (< 32rem)

  • Vertical stack layout
  • Media at top (16:9 aspect ratio)
  • Body content below

Wide Layout (≥ 32rem)

  • Horizontal layout
  • Media on left (150px square)
  • Body content on right (60% width)

Styling Customization

The card supports several CSS custom properties for customization:

  • --card-background
  • --card-color
  • --card-border-color
  • --card-border-width
  • --card-radius
  • --card-padding
  • --card-gap
  • --card-header-padding
  • --card-header-padding-block-end
  • --card-footer-padding
  • --card-footer-padding-block-start
  • --card-shadow
  • --card-hover-transform
  • --card-hover-shadow

These public variables work directly on a card or from a scoped ancestor:

.pricing-grid {
--card-padding: 2rem;
--card-radius: 1rem;
}
.pricing-grid > card[data-featured] {
--card-border-color: var(--accent);
}

Card internals use private computed aliases, so inherited public overrides are not replaced by the component selector.

card-header and card-footer use the card inset when they are direct children of a card. When they are nested in card-body, the body owns the inset instead, so padding is never doubled.

Usage Example

<card>
<card-media>
<img src="article-cover.jpg" alt="A CSS layout drawn on a whiteboard">
</card-media>
<card-body>
<card-header>Designing with container queries</card-header>
<card-content>
<p>A card can respond to the space it receives instead of the viewport.</p>
</card-content>
<card-footer>
<button type="button">Read article</button>
</card-footer>
</card-body>
</card>

Hover Effects

  • Transform: Moves up 2px by default
  • Elevation: Flat by default; opt in with --card-hover-shadow and --card-hover-transform

Technical Implementation

Selector scope

:is(card, [data-card], .card) { /* card host */ }
:is(card-body, [data-card-body], .card-body) { /* card body */ }

Explicit host and part selectors prevent unrelated page content from inheriting card layout.

Container Queries

@container card-container (min-width: 32rem) {
/* Styles applied when card is at least 32rem wide */
}

The card establishes itself as a container with container-type: inline-size.

CSS Nesting

Uses native CSS nesting for organized, hierarchical styles.

Browser Support

Cards follow the shared Browser Support baseline. Their narrow, stacked composition is the default; the horizontal arrangement is a container-query enhancement when enough space is available.

Accessibility

  • Semantic structure with proper content hierarchy
  • Hover effects respect prefers-reduced-motion
  • Color contrast maintained through theme variables
  • Keyboard navigation support (inherited from base styles)