·8 min read·

Container queries are finally here.

Twenty years of media-query-driven responsive design. Now CSS components can size themselves by their container, not the viewport. Here is why this matters more than the spec sounds, with examples, browser support data, and the patterns we now default to.

Container queries became a stable, cross-browser CSS feature this month. They've been promised since the early 2010s and dismissed as 'never going to happen' for most of the decade. They are now here. This matters.

Browser support, finally

BrowserVersionStatus
Chrome105+Stable since Aug 2022
Edge105+Stable since Aug 2022
Safari16+Stable since Sep 2022
Firefox110+Stable since Feb 2023
Mobile Safari (iOS)16+Stable since iOS 16
Samsung Internet20+Stable
Container query support across major browsers, February 2023.

The problem they solve

Media queries are based on the viewport. But a component might appear in a 200px sidebar on one page, a 800px column on another, and a full-bleed hero on a third. The same component, three different sizes, with a media query that knows nothing about any of them. We've been working around this for years — usually with variants in our design system ('Card.Compact', 'Card.Full', 'Card.Sidebar') that all have slightly different rules duplicated across files.

What container queries change

  • 01Components can declare 'when my container is wider than X, I look like this'.
  • 02Layout decisions belong to the component, not to the page it lives in.
  • 03Design systems stop needing fifteen variants per component for different contexts.
  • 04Editorial layouts (long-form articles with embedded media) finally feel like they were designed for the web.
  • 05Reusable cards, panels, navigation strips can be dropped into any layout context and adapt themselves.

What it looks like in practice

A real card component using container queries. Same markup, three different layouts depending on the container width — no JavaScript, no media-query awareness, no parent-aware variants.

components/card.csscss
/* The card's wrapper opts into container-query awareness */
.card-wrap {
  container-type: inline-size;
  container-name: card;
}

/* The card itself uses @container rules */
.card {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

/* When the container is wide enough, switch to horizontal layout */
@container card (min-width: 480px) {
  .card {
    flex-direction: row;
    align-items: center;
    gap: 24px;
  }
  .card__image {
    flex: 0 0 200px;
  }
}

/* When wider still, give the image more room */
@container card (min-width: 720px) {
  .card__image {
    flex-basis: 320px;
  }
  .card__title {
    font-size: 2rem;
  }
}

Layout decisions belong to the component, not to the page it lives in. Twenty years of fighting that idea, now finally a primitive that supports it natively.

How we use them now

  • 01Every new component declares its own container queries — never relies on viewport size unless it has a strong reason.
  • 02Card components have one set of CQ rules and just work in any grid layout we drop them into.
  • 03We removed roughly half the @media rules from our internal component library in the first month.
  • 04We use container-type: inline-size as the default; container-type: size only when we genuinely care about height too.
  • 05Container names are scoped per component — never global — to avoid accidental matches.

When to still use media queries

  • 01Top-level page layout — the page itself is the container, viewport size is what matters.
  • 02Navigation chrome — the global navigation pattern is viewport-driven.
  • 03Typography scales — body type rarely benefits from container-query thinking.
  • 04Anything that legitimately changes by device class rather than by available space.

If you haven't tried them yet, do. It will rewire how you think about responsive design. The mental model is healthier; the components are more reusable; the design system gets smaller, not larger, every quarter.

Talk to Remiam about a system like this.