Picture this: you build a product card component. It looks perfect in the main content area – image on the left, details on the right, nice and spacious. Then your designer drops it into a 280px sidebar. It implodes. Text overflows, the image squishes, the whole thing looks like a car crash.
You reach for a media query. But wait – the sidebar is narrow on desktop too, not just mobile. Your @media (max-width: 768px) fires on phones, sure, but the card in the sidebar is still broken at 1440px because media queries have no idea where your component lives. They only know the viewport.
This is the exact problem container queries were built to solve. Drag the slider and see for yourself:
I started using them about a year ago and they changed how I think about component design. Instead of asking “how wide is the screen?”, your CSS asks “how wide is my parent?” – and that distinction matters more than you’d expect.
What Are Container Queries?
Container queries let you apply styles to an element based on the size of its parent container, not the browser viewport. The concept builds on CSS containment. You mark an element as a “container”, then write conditional styles that kick in when that container reaches certain dimensions.
The result is truly portable components. A card, a navigation menu, or a widget can adapt its layout based on whatever space it’s given. Screen size becomes irrelevant.
Container Queries vs. Media Queries
The difference comes down to what each one responds to.
| Media Queries | Container Queries | |
|---|---|---|
| Responds to | Viewport / device | Parent container |
| Scope | Global (whole page) | Local (component) |
| Reusability | Breakpoints break when component moves | Same component works everywhere |
| Best for | Page layout, user preferences | Component-level responsiveness |
Media queries ask “how big is the screen?” Container queries ask “how much space does my parent give me?” A card in a 300px sidebar and the same card in a 900px main column get different styles automatically.
They complement each other. Use media queries for macro layout (page grid, navigation strategy) and container queries for micro layout (how individual components adapt internally).
How Container Queries Work
Setting up container queries takes two steps: define a container, then query it.
Step 1: Define a Container
Use the container-type property to mark an element as a query container:
.card-wrapper {
container-type: inline-size;
}The container-type property accepts these values:
inline-size– enables queries on the inline axis (width in horizontal writing modes). This is what you’ll use most of the time.size– enables queries on both axes. Requires the container to have an explicit height.normal– the default. Not a size container, but still works as a style query container.
You can also give the container a name with container-name:
.card-wrapper {
container-type: inline-size;
container-name: card;
}Or use the shorthand container property (name first, then type after the slash):
.card-wrapper {
container: card / inline-size;
}Step 2: Query the Container
Use the @container at-rule to write conditional styles. These styles apply to the container’s descendants when the condition is met:
@container (min-width: 500px) {
.card {
flex-direction: row;
}
}You can also use the modern range syntax, which reads more naturally:
@container (width > 500px) {
.card {
flex-direction: row;
}
}
@container (300px < width < 600px) {
.card {
font-size: 0.9em;
}
}To target a specific named container:
@container card (width > 500px) {
.card {
flex-direction: row;
}
}Without a name, @container targets the nearest ancestor with a containment context. Naming your containers avoids unexpected behavior as your component tree grows.
Live Examples
Drag the sliders below to resize each container and watch the components adapt in real time.
Responsive Card Component
This card switches between a vertical (stacked) and horizontal (side-by-side) layout depending on its container width. The breakpoint is at 420px.
Adaptive Sidebar Navigation
This navigation shows only icons when narrow and expands to show labels when the container is wide enough. The same component works in a collapsed 60px sidebar or a full 240px sidebar – no viewport breakpoints needed.
Dashboard Widget
A stats widget that shows a compact number-only layout in small containers and expands to include a mini bar chart when there’s enough room.
Container Query Length Units
Container queries also introduce a set of length units relative to the container’s dimensions, similar to viewport units but scoped locally:
| Unit | Meaning | Viewport Equivalent |
|---|---|---|
cqw | 1% of container width | vw |
cqh | 1% of container height | vh |
cqi | 1% of container inline size | vi |
cqb | 1% of container block size | vb |
cqmin | Smaller of cqi or cqb | vmin |
cqmax | Larger of cqi or cqb | vmax |
These are useful for fluid typography and spacing that scales with the container:
.card-title {
font-size: clamp(14px, 10px + 1.5cqi, 22px);
padding: clamp(0.5rem, 5cqi, 1.5rem);
}If no eligible container exists in the ancestor tree, these units fall back to the corresponding small viewport units.
Gotchas and Limitations
Container queries have a few sharp edges that trip up beginners:
Containers cannot style themselves. You can only style descendants inside a @container rule. The container element itself is off-limits. Think of it as “you cannot style what you query.”
Containers must get their size externally. Setting container-type: inline-size establishes size containment. This means the container’s width is calculated ignoring its children. The container needs to get its size from the layout context – a CSS Grid cell, a Flexbox parent, or an explicit width.
You cannot use var() in query conditions. This does not work:
/* This is invalid and will be ignored */
@container (min-width: var(--breakpoint)) {
.card { flex-direction: row; }
}container-type: size requires explicit height. If you need to query both width and height, the container must have a defined height. In most cases, inline-size is all you need.
Avoid making <html> or <body> containers. Applying container-type to root elements can cause unexpected layout behavior. Use semantic elements like <main>, <aside>, or wrapper divs instead.
Browser Support
Container size queries have excellent browser support as of 2026:
| Browser | Supported Since |
|---|---|
| Chrome | 106+ (Sep 2022) |
| Edge | 106+ (Sep 2022) |
| Firefox | 110+ (Feb 2023) |
| Safari | 16.0+ (Sep 2022) |
| Safari iOS | 16.0+ |
Container size queries have roughly 96% global browser support and are considered production-ready. No polyfill needed for modern projects.
FAQs
Common questions about CSS container queries:
prefers-color-scheme or prefers-reduced-motion. Use container queries for component-level responsiveness where elements need to adapt to their available space.@container rules. A nested query targets the nearest matching ancestor container. If you name your containers, the inner query targets the named container while the outer query targets a different one. This is useful for components inside components that each need their own responsive behavior.container-type set, unnamed @container queries will not match and their styles will not apply. Container query length units like cqi will fall back to the corresponding small viewport units (svi). Always make sure a container is defined somewhere in the ancestor chain.@container style(--theme: dark). Unlike size queries, every element is implicitly a style container - no container-type needed. As of 2026, style queries for custom properties work in Chrome, Edge, and Safari, but not yet in Firefox.@container rule can only style the container's descendants, never the container element itself. If you need to style the container based on its own size, add an inner wrapper element and make the outer element the container.Summary
Container queries let your components respond to their available space instead of the viewport. Define a container with container-type: inline-size, query it with @container, and your component adapts wherever it’s placed – sidebar, main content, modal, dashboard grid.
Combined with CSS Grid and Flexbox for layout, container queries complete the picture for building truly reusable, responsive components.

