Container Queries in CSS: Responsive Layouts Without Media Queries
Media queries solved responsive web design a decade ago, and they have been the wrong abstraction for component-level responsiveness ever since. A media query asks "how wide is the viewport?" but a component in a sidebar, a modal, or a three-column grid does not care about the viewport — it needs to know how wide its own container is. That gap between what media queries measure and what components need has generated thousands of lines of workaround JavaScript, breakpoint-specific utility classes, and frustrated developers.
Container queries fix this. A component styled with container queries adapts to the width of its parent container, not the viewport. The sidebar card looks different from the main-content card not because of a viewport breakpoint, but because the sidebar is narrower. This guide covers the practical implementation: how to structure containment contexts, which patterns work in production, what breaks when you adopt container queries, and the specific component types that benefit most.
Why This Matters Now
Container queries have been in browsers since late 2023, but production adoption has been cautious. In 2026, the concerns that slowed adoption are resolved:
- Browser support is universal. Every major browser supports
@containerqueries. - DevTools support is mature. Chrome, Firefox, and Safari all show container query boundaries in their inspector, making debugging straightforward.
- CSS frameworks have caught up. Tailwind 4, Open Props, and other utility frameworks include container query utilities.
- Real-world patterns are documented. Two years of production use has established which patterns work and which create problems.
If you skipped container queries in 2024 because the ecosystem was not ready, it is time to adopt them. The CSS innovations guide covers the broader trend of CSS replacing JavaScript — container queries are the most impactful example for layout work.
How Container Queries Work
Two pieces are required:
1. Declare a Containment Context
The parent element must establish a containment context:
.card-wrapper {
container-type: inline-size;
container-name: card;
}
container-type: inline-size tells the browser to track the inline (horizontal in LTR) size of this element and make it available for container queries. container-name is optional but useful when you have nested containment contexts.
2. Query the Container
@container card (min-width: 400px) {
.card {
display: grid;
grid-template-columns: 200px 1fr;
gap: var(--space-4);
}
}
@container card (max-width: 399px) {
.card {
display: flex;
flex-direction: column;
}
}
The card switches from a vertical stack to a horizontal grid layout at 400px — but 400px of its container, not the viewport. Place this card in a 600px main column and it uses the grid layout. Place it in a 300px sidebar and it stacks vertically. Same component, same CSS, no JavaScript, no viewport breakpoints.
Patterns That Work in Production
Responsive Card Components
The most common and most valuable container query pattern. A card that adapts its layout — image position, text truncation, metadata visibility — based on available space.
.card-container {
container-type: inline-size;
}
/* Compact: stack everything vertically */
@container (max-width: 299px) {
.card__image { aspect-ratio: 16/9; }
.card__meta { display: none; }
}
/* Standard: image left, content right */
@container (min-width: 300px) and (max-width: 599px) {
.card { grid-template-columns: 120px 1fr; }
.card__meta { font-size: var(--text-sm); }
}
/* Wide: larger image, full metadata */
@container (min-width: 600px) {
.card { grid-template-columns: 200px 1fr; }
.card__meta { font-size: var(--text-base); }
}
This same card works in a single-column layout, a two-column layout, a sidebar, and a modal. The component handles its own responsiveness.
Navigation Components
A navigation bar that collapses from horizontal links to a compact hamburger-style layout based on its container width, not the viewport. This is particularly useful for navigation inside dashboard panels, modal sidebars, or any context where the nav does not span the full viewport.
Data Tables
Tables that switch from full multi-column layouts to stacked key-value pair layouts when their container is narrow. This eliminates the common pattern of hiding table columns at mobile breakpoints — instead, the table restructures itself to present all data in a narrow-friendly format.
Typography Scale Adjustments
The typography and readability guide covers type scales and line length. Container queries let you adjust the type scale based on the container measure (line length). A narrow container gets a smaller heading size and tighter line height. A wide container gets larger headings. This keeps typographic proportions correct regardless of layout context.
Containment Gotchas
Container queries are not free. The container-type: inline-size declaration creates a CSS containment context, which has layout implications:
Intrinsic Sizing Breaks
An element with container-type: inline-size cannot size itself based on its children in the inline direction. It must have an explicit or inherited width. This means:
/* This breaks — the container needs children to determine width,
but children need the container to evaluate @container queries */
.auto-width-container {
container-type: inline-size;
width: fit-content; /* PROBLEM: circular dependency */
}
The fix: only apply containment to elements that already have a defined width from their parent layout (grid cells, flex items with explicit basis, block elements in a sized container).
Nested Containment
When containers are nested, @container queries target the nearest ancestor containment context by default. Use container-name to target a specific ancestor:
.outer { container-type: inline-size; container-name: layout; }
.inner { container-type: inline-size; container-name: card; }
/* Targets the card container, not the layout container */
@container card (min-width: 300px) { /* ... */ }
/* Targets the outer layout container */
@container layout (min-width: 800px) { /* ... */ }
Without names, nested containers create confusing behaviour where queries target whichever containment context is nearest in the DOM tree.
Container Queries vs Media Queries: When to Use Each
Container queries do not replace media queries entirely. Each has a correct use case:
Use container queries for:
- Component-level layout changes (cards, navigation panels, form groups)
- Any component that appears in multiple layout contexts
- Design system components that need to work in any container width
Use media queries for:
- Page-level layout changes (switching from sidebar + main to single column)
- Print stylesheets
- User preference queries (
prefers-color-scheme,prefers-reduced-motion) - Viewport-specific concerns (sticky headers, full-screen modals)
The semantic HTML layouts guide covers the structural patterns that define those page-level layout zones. Container queries handle the components within those zones.
Migrating From Media Queries
For an existing component library built on media queries:
- Identify components used in multiple layout contexts. Cards, navigation, data displays — anything that lives in both a wide main column and a narrow sidebar.
- Add
container-type: inline-sizeto the component wrapper. Not the component itself, but its direct parent. - Convert
@mediaqueries to@containerqueries. Change the breakpoint values — viewport breakpoints and container breakpoints are different. A card at 600px container width is not the same context as 600px viewport width. - Test in all layout contexts. The whole point is that the component now adapts to any container size. Test it in sidebar, main column, modal, and full-width contexts.
- Remove JavaScript size detection. If you had ResizeObserver or element-width measurement JS for component responsiveness, it can go.
Performance Characteristics
Container queries are handled by the browser's layout engine, not your JavaScript. The performance is essentially free — the layout engine already computes element sizes during the layout pass, and container queries add minimal overhead to that computation.
However, excessive containment contexts can affect layout performance in pathological cases. If every element on the page has container-type: inline-size, you are creating hundreds of containment contexts that the browser must track. In practice, containment at the component-wrapper level (10–30 contexts per page) has no measurable performance impact.
Checklist
- [ ] Components in multiple layout contexts use container queries, not media queries
- [ ]
container-type: inline-sizeapplied to component wrappers, not components themselves - [ ] No circular sizing dependencies between containers and their children
- [ ] Named containers used when nesting containment contexts
- [ ] Container query breakpoints calibrated to component needs, not viewport widths
- [ ] JavaScript element-width detection removed for migrated components
- [ ] Typography scales adapted via container queries for variable-width contexts
- [ ] Page-level layout changes still use media queries
- [ ] All container-queried components tested in narrow, medium, and wide contexts
- [ ] DevTools container overlay used during development for debugging
FAQ
Can I use container queries with Tailwind CSS?
Yes. Tailwind 4 includes @container utilities. You can use @container/card variants in your class names to apply container-query-based styles.
Do container queries work with CSS Grid?
Yes, and they work particularly well. Grid cells have explicit sizes defined by the grid template, which makes them natural containment contexts. Apply container-type: inline-size to grid cells and use container queries inside them.
What about container queries for height?
container-type: size tracks both width and height, but querying height creates more containment restrictions (the element also loses intrinsic block sizing). Height-based container queries are rarely needed and create more problems than they solve. Stick to inline-size unless you have a specific use case.
Next Steps
- Read the CSS innovations guide for more features replacing JavaScript patterns
- Review the typography and readability guide for type scale decisions that benefit from container-aware sizing
- Check the semantic HTML layouts guide for the page-level structure that creates container contexts
- Explore the layout demos to see different structural approaches
- Browse all guides for more implementation patterns
