Media queries changed how we build for multiple screen sizes. Container queries change how we build components. The difference sounds subtle but the practical impact is significant: a card component that adjusts its own layout based on the width of the column it sits in — not the width of the viewport — can be dropped anywhere on a page and just work, regardless of context.
Container queries shipped in all major browsers in 2023 and are now baseline. In 2026, there is no good reason to not use them. This post explains how they work and where they make the biggest difference.
The Problem Media Queries Don’t Solve
Imagine a product card component. In a full-width layout it should display the image on the left and text on the right. In a sidebar it should stack vertically. With media queries, you can’t express this cleanly — you’d write breakpoints based on the viewport, but the card’s available width depends on the column it’s in, not the screen. You end up writing context-specific overrides, breaking the component’s reusability.
Container queries solve this by letting a component query its own container’s size instead of the global viewport.
Basic Syntax
Two steps: declare the container, then query it from within.
/* Step 1: declare a containment context */
.card-wrapper {
container-type: inline-size;
container-name: card; /* optional, needed for named queries */
}
/* Step 2: query the container from a child */
@container card (min-width: 400px) {
.card {
display: grid;
grid-template-columns: 200px 1fr;
gap: 1rem;
}
}
@container card (max-width: 399px) {
.card {
display: flex;
flex-direction: column;
}
}
container-type: inline-size tells the browser this element is a containment context for its children, measured along the inline axis (width in horizontal writing modes). container-type: size enables both width and height queries, but requires the container to have a defined height — inline-size is more useful in most layouts.
A Real Example: The Adaptive Card
Here is a full card component that switches between stacked and side-by-side layouts at 500px container width, and adjusts its typography at narrower widths:
.card-container {
container-type: inline-size;
}
.card {
border: 1px solid #e0e0e0;
border-radius: 8px;
overflow: hidden;
background: #fff;
}
.card-image {
width: 100%;
aspect-ratio: 16 / 9;
object-fit: cover;
}
.card-body {
padding: 1rem;
}
.card-title {
font-size: 1rem;
margin: 0 0 0.5rem;
}
/* Wide container: side-by-side layout */
@container (min-width: 500px) {
.card {
display: grid;
grid-template-columns: 200px 1fr;
}
.card-image {
width: 200px;
height: 100%;
aspect-ratio: auto;
}
.card-title {
font-size: 1.25rem;
}
}
/* Very narrow: compact typography */
@container (max-width: 280px) {
.card-title {
font-size: 0.875rem;
}
.card-body {
padding: 0.5rem;
}
}
Drop .card-container into a 3-column grid, a sidebar, or a full-width hero section — the card adapts to whatever space it’s given, with no viewport-level overrides needed.
container-type: style — Querying CSS Custom Properties
Container queries are not limited to dimensions. Style queries let you query the computed value of a custom property on the container:
.theme-wrapper {
container-type: style;
--theme: dark;
}
@container style(--theme: dark) {
.card {
background: #1a1a2e;
color: #fff;
border-color: #2c3e50;
}
}
@container style(--theme: light) {
.card {
background: #fff;
color: #333;
border-color: #e0e0e0;
}
}
Style queries are still Chromium-only as of mid-2026 — they’re in the spec but Firefox and Safari support is pending. Use them with a @supports check or as progressive enhancement. Dimension queries are fully cross-browser.
Container Units
Alongside container queries, CSS introduced container query units: cqi, cqb, cqw, cqh, cqmin, cqmax. These work like vw/vh but relative to the nearest named container instead of the viewport.
.card-container {
container-type: inline-size;
}
.card-title {
/* font size is 5% of the container's inline size */
font-size: clamp(0.875rem, 5cqi, 1.5rem);
}
Container units make fluid typography inside components straightforward, without needing to know in advance where the component will be placed.
Nesting Container Queries
Containers can be nested. Each @container query resolves against the nearest ancestor that is a containment context, unless you use a named container to target a specific ancestor:
.outer { container-type: inline-size; container-name: outer; }
.inner { container-type: inline-size; container-name: inner; }
/* This targets the inner container */
@container inner (min-width: 300px) { ... }
/* This targets the outer container, skipping the inner one */
@container outer (min-width: 800px) { ... }
When to Use Container Queries vs. Media Queries
They solve different problems and work best together:
- Use media queries for layout changes that are truly about the viewport: the overall page grid shifting from single to multi-column, a navigation bar collapsing to a hamburger, the global font size stepping up for large screens.
- Use container queries for component-level layout: how a card, a list item, a widget, or a form field arranges its own internals based on available space.
A well-architected page uses both: media queries define the page-level grid, container queries let the components inside it handle their own responsiveness.
Browser Support and Polyfills
Inline-size container queries are supported in Chrome 105+, Safari 16+, Firefox 110+, and Edge 105+. This covers over 95% of active browser sessions globally. You can use them without a polyfill for most audiences today.
If you need to support older browsers, the container-query-polyfill from the Chrome team provides a JavaScript fallback using ResizeObserver. It handles the most common cases and is a reasonable bridge while legacy browser share continues to decline.
Container queries do not replace media queries and they are not a magic solution to all layout problems. What they do is make components genuinely self-contained in a way that was not possible before. If you have ever maintained a stylesheet full of context-specific overrides for the same component placed in different locations, you will find them immediately useful.