Articles /

Widely supportedlayout

Container queries in 2026

The complete guide to @container — why viewport-based media queries aren't enough.

The problem: media queries break component reuse

You build a card component. It works in the main column. Then someone puts it in a sidebar. Suddenly it's too wide, the title wraps awkwardly, and the three-column grid turns into a mess. You add breakpoint overrides for the sidebar context. Now the card has two different breakpoint sets depending on where it's used.

This is the fundamental problem with media queries: they respond to the viewport, not the component's actual context. Container queries fix this at the source.

How container queries work

You declare a "query container" on a wrapper element. Children can then use @container to apply styles based on the container's size.

/* Step 1: declare the container */
.card-wrapper {
  container-type: inline-size;
  container-name: cards; /* optional — use for nested containers */
}

/* Step 2: query it from children */
.card-grid {
  display: grid;
  gap: 1rem;
}

@container cards (min-width: 28rem) {
  .card-grid { grid-template-columns: repeat(2, 1fr); }
}

@container cards (min-width: 44rem) {
  .card-grid { grid-template-columns: repeat(3, 1fr); }
}

Now put .card-wrapper anywhere — sidebar, main column, modal, full-bleed section — and the card grid adapts to its actual space. No new breakpoints to write.

Container types

  • inline-size — queries the inline axis (width in horizontal writing modes). The most common type. Only the inline dimension creates containment.
  • size — queries both axes (width and height). Requires explicit height on the container. Use sparingly.
  • style — queries custom property values (e.g. @container style(--variant: compact)). Enables design-system-level conditional styling based on tokens.
  • scroll-state — queries scroll state (stuck, snapped, overflow). Experimental in 2026.

Container units

Inside a @container query or inside a container, you can use container-relative units:

/* cqi = 1% of container's inline size */
.card h2 { font-size: clamp(0.875rem, 4cqi, 1.25rem); }

/* cqw, cqh, cqmin, cqmax also available */

This lets typography scale relative to the container, not the viewport — combined with clamp(), it gives you truly adaptive components.

Style queries (coming)

Style container queries let you query CSS custom property values, enabling a "props in CSS" pattern:

.button-group {
  container-type: style;
}

@container style(--size: compact) {
  .button { padding: 0.3rem 0.6rem; font-size: 0.8rem; }
}

@container style(--size: large) {
  .button { padding: 0.75rem 1.5rem; font-size: 1rem; }
}

Set --size: compact on a container in CSS or HTML and all children adapt. This is the CSS equivalent of passing a "size" prop in React — without JavaScript.

When to use container queries vs media queries

  • Use media queries for page-level layout changes — main column + sidebar, header nav changes, hero section sizing.
  • Use container queries for component-level layout — any card, list, form, or widget that's reused in multiple contexts.
  • Combine them: media queries for the overall page frame, container queries for what's inside it.
Browser support: Chrome 105+, Safari 16+, Firefox 110+. Widely available. Fallback: single-column layout (the default CSS) is always the safe base.