CSS Container Queries Explained With Examples
Photo by Unsplash on Unsplash
Table of Contents
The Short Version
The difference sounds academic until you've built the same card component three times. Media queries can only ask one question — how wide is the window — which is the wrong question when the same card appears in a wide main column, a narrow sidebar and a two-up grid.
With media queries you end up with modifier classes: `card--compact`, `card--wide`, `card--sidebar`. The component doesn't know where it is, so you have to tell it.
Container queries let the component work it out. That's the entire pitch, and after using them for a year I'd say it holds up.
The Problem Media Queries Never Solved
Component-driven development broke the assumption. The same card renders in six contexts, and the viewport tells it nothing useful about the space it actually has. A 1400px viewport can contain a 240px sidebar, and a card in that sidebar has no business using the wide layout.
The workarounds were all bad in the same way. Modifier classes push layout knowledge up to whoever renders the component. JavaScript with ResizeObserver works but costs a render cycle and runs after paint, so you see the wrong layout flash first.
Container queries move the question to where the answer lives. The component measures its own context in CSS, at layout time, with no script and no flash. That's the structural improvement — not new visual capability, but a correct place to ask the question.
Declaring a Container
```css .card-wrapper { container-type: inline-size; container-name: card; } ```
`inline-size` means the container is queryable on its inline dimension — width in horizontal writing modes. That's what you want almost every time. `size` makes both dimensions queryable but requires the element to have a definite block size, which usually means giving it an explicit height, and that's rarely worth it.
The shorthand `container: card / inline-size` sets both at once.
One detail that trips people up: `container-type` applies containment, which means the container's size can no longer depend on its children's size in the queried dimension. Set `inline-size` on an element whose width comes from its content and you'll watch it collapse. Put the container on a wrapper that gets its width from the layout, and keep the component itself as a child.
Writing the Query
```css @container card (min-width: 400px) { .card { display: grid; grid-template-columns: 140px 1fr; } } ```
The container name is optional — leave it out and the query resolves against the nearest ancestor that's a container. Naming matters once you have nested containers and need to target a specific one.
Range syntax works too: `@container (400px <= width <= 700px)`, which is more readable than pairs of min and max declarations once you've got three breakpoints.
The rule everyone hits once: you cannot query the container from inside itself. `.card { container-type: inline-size }` followed by a query that styles `.card` does nothing, because the query only applies to descendants. Wrapper queries, child styles. Once that clicks, the rest is mechanical, and choosing sensible breakpoints becomes a question about the component rather than about devices.
Container Units
```css .card-title { font-size: clamp(1rem, 5cqi, 1.75rem); } ```
That scales the heading with the container rather than the viewport, which is exactly what you want for a component that appears at several widths. Combined with `clamp()` you get fluid type with sensible floors and ceilings, and no breakpoints at all for some components.
`cqmin` and `cqmax` resolve to the smaller or larger of the two dimensions, which is handy for square-ish elements.
These units only resolve inside a container — outside one they fall back to the small viewport units, which produces confusing results if you use them by accident. If you're already comfortable with CSS units like em, rem and vh, container units slot in as the same idea with a different reference box.
Style Queries, Briefly
```css @container style(--theme: dark) { .card { background: #111; color: #eee; } } ```
This is newer than size queries. Chrome and Safari shipped it earlier, and Firefox added support in 2026, so it's now available across the major engines — though I'd still check your own analytics before relying on it for anything critical.
The use case is theming and variants without extra classes. Set a custom property on a parent and descendants respond, which keeps the variant logic in one place.
Worth being clear about the limitation: style queries currently work with custom properties, not arbitrary CSS properties. You can't ask "is this element `display: flex`". The Baseline data on web.dev is the reference I check before assuming a CSS feature is safe, and it tracks both flavours separately.
Where They Actually Pay Off
Design systems benefit most. A component library that ships container queries hands consumers something that just works in any slot, which removes an entire category of documentation and an entire category of bug report.
Dashboards with resizable panels are the case where nothing else works. The viewport never changes while the user drags a divider, so media queries are simply blind to it.
Where they don't help: page-level layout. Deciding whether the whole page is one column or three is genuinely a viewport question, and media queries answer it correctly. Use both. They're not competing, and the sensible rule is media queries for the page shell, container queries for anything reusable inside it.
Migrating Without a Rewrite
Add the wrapper, set `container-type: inline-size`, then translate each modifier class into a `@container` rule. Delete the class from the call sites once the query covers it. The diff is usually smaller than expected because the modifiers were mostly duplicating each other.
Fallbacks are largely unnecessary now, but if you support genuinely old browsers, `@supports (container-type: inline-size)` lets you keep the old rules as a base and layer the new behaviour on top.
One debugging tip that saves time: browser devtools mark container elements with a badge in the elements panel, and clicking it highlights the container box. When a query isn't firing, it's almost always because the container isn't the element you assumed it was, and that badge tells you in a second. Our note on CSS specificity covers the other half of the "why isn't this rule applying" question.
Frequently Asked Questions
What is the difference between a container query and a media query?
A media query responds to the viewport size, while a container query responds to the size of a specified ancestor element. That lets one component adapt correctly whether it sits in a narrow sidebar or a wide main column, without the parent telling it which layout to use.
Are CSS container queries safe to use in 2026?
Yes for size queries — they've been supported in Chrome, Edge, Firefox and Safari since 2023 and are considered widely available. Style queries are newer, with Firefox support arriving in 2026, so check your own traffic before depending on them.
Why is my container query not working?
The most common cause is querying the container from inside itself. A container query only styles descendants of the container, never the container element. Put container-type on a wrapper and style the child, and check that the wrapper's width comes from the layout rather than from its content.
What does container-type: inline-size do?
It marks the element as a query container measurable on its inline axis — width in normal horizontal writing — and applies containment on that axis. That containment means the element's width can no longer be determined by its children, which is why a content-sized element can collapse when you add it.
What are cqw and cqi units?
They're container-relative lengths: cqw is 1% of the container's width and cqi is 1% of its inline size. They pair well with clamp() for fluid type that scales with the component rather than the window, much like the [viewport and font units](/blog/css-units-explained-px-em-rem-vh-vw) do at page level.
Try ToolsFuel
23+ free online tools for developers, designers, and everyone. No signup required.
Browse All Tools