Container queries — component-level responsiveness
A media query can only ever ask 'how wide is the viewport' — container queries ask the more useful question 'how wide is the space THIS component actually has,' which media queries have never been able to answer.
2 min read
The gap media queries always had: a component doesn't know its own container's width
/* A media query can only ever check the VIEWPORT, never a component's actual
available space — this card looks identical whether it's the full width
of a wide page or squeezed into a narrow sidebar, because the viewport
itself hasn't changed size in either case */
@media (min-width: 600px) {
.card { display: flex; }
}The same .card component might render at very different actual widths depending on where it's placed — full-bleed in a wide main column, or squeezed into a 250px sidebar — but a @media query has no way to know that; it only ever sees the viewport's total width, which is identical in both placements. This is the real, structural gap container queries close: the ability for a component to respond to its own available space, not the page's.
Declaring a container, then querying it
.card-wrapper {
container-type: inline-size; /* opts this element in as a queryable container, tracking its own width */
container-name: card; /* optional — names it for clarity when nesting multiple containers */
}
@container card (min-width: 400px) {
.card { display: flex; gap: 16px; } /* applies when THIS card's wrapper is at least 400px wide */
}container-type: inline-size is the opt-in step — without it, an element isn't a queryable container at all, and @container rules targeting it simply never match. Once declared, @container works almost identically to @media syntactically (the same min-width/max-width conditions), but evaluates against the named container's actual current width, not the viewport — the same .card component now genuinely adapts differently depending on whether its wrapper happens to be in a wide column or a narrow sidebar.
Why this genuinely changes how reusable components get built
Before container queries, a component meant to be reused in genuinely different layout contexts (a card that appears both in a 3-column grid and a narrow sidebar) had no CSS-only way to adapt to each context — the common workarounds were either accepting one compromise layout that worked "well enough" everywhere, or reaching for JavaScript (a ResizeObserver) to measure the container and toggle a class manually. Container queries make the CSS-only version of that adaptation possible for the first time, closing a real, long-standing gap between "build a truly reusable, self-adapting component" and "the CSS language could actually express that."
Further reading
Check your understanding
A quick comprehension check — not tracked, not graded, just for you.
1. What real gap in media queries do container queries close?
2. What does `container-type: inline-size` actually do?
3. What did teams have to do before container queries to make a component adapt to its own container's width?