CSS Container Queries Reference
Generate @container CSS, explore container units (cqw, cqi, cqb), style queries, and nested container patterns
Container Configuration
Establishes a containment context for the inline dimension only (the horizontal axis in left-to-right writing modes). This is the most common choice — it does not require block-size containment, so the element can still grow vertically to fit its content.
Named containers can be targeted from nested @container rules
@container Breakpoints
Generated CSS
/* Container element — establishes the query context */
.card-wrapper {
container: card / inline-size;
}
/* Query: min-width: 400px */
@container card (min-width: 400px) {
.card {
display: flex;
gap: 1rem;
}
}
/* Query: min-width: 700px */
@container card (min-width: 700px) {
.card {
grid-template-columns: 1fr 2fr;
font-size: 1.125rem;
}
}Your card component works perfectly in the main content area. Then product drops it into a 280px sidebar and everything breaks — the image overflows, the title wraps awkwardly, the button gets cropped. Media queries can’t help because they respond to the viewport, not the container. Container queries fix this at the CSS level.
Why This Reference (Not MDN or a Blog Post)
MDN’s container query documentation is split across 5 separate pages and doesn’t include a generator. This reference covers everything in one page with copy-ready examples, including container query units (cqw, cqh, cqmin, cqmax), style queries, and nested containers. All processing happens in your browser.
What Are CSS Container Queries?
CSS Container Queries let you apply styles to an element based on the size or computed style of its parent container — not the viewport. This makes components truly reusable: a card adapts to its column width whether it sits in a sidebar, a main content area, or a modal.
/* 1. Mark the parent as a container */
.card-wrapper {
container-type: inline-size;
container-name: card;
}
/* 2. Query the container — not the viewport */
@container card (min-width: 400px) {
.card {
display: flex;
flex-direction: row;
}
}
Container queries solve the long-standing problem with media queries: a component can’t know its own available space. With container queries, the component itself declares what it looks like at different sizes.
container-type: The Three Values
The container-type property establishes the containment context and determines which features can be queried.
inline-size
The most common value. Establishes containment for the inline dimension (width in left-to-right writing modes). The element can be queried by width, inline-size, and related features.
.sidebar-widget {
container-type: inline-size;
}
Unlike size, inline-size containment does not require a fixed height — the element can still grow to fit its content. This makes it suitable for the vast majority of responsive component patterns.
size
Establishes containment for both inline and block dimensions (width and height). Enables all queryable features: width, height, inline-size, block-size, aspect-ratio, and orientation.
.embed-widget {
container-type: size;
height: 300px; /* Block size must be defined */
}
@container (orientation: landscape) {
.embed-controls { flex-direction: row; }
}
Important: Because block containment prevents the element from auto-sizing based on content, you must give the element a defined height (or place it inside a parent with a known height). Using size unnecessarily can break layout flow.
normal
No size containment. The element cannot be queried for size features but can still participate in style queries (@container style()). This is the default value.
.theme-root {
container-type: normal;
container-name: theme;
--color-scheme: light;
}
@container theme style(--color-scheme: dark) {
.card { background: #1a1a1a; }
}
container-name: Named Containers
The container-name property assigns a name to a container. Named containers let you target a specific ancestor when multiple container contexts are nested.
/* Unnamed container — @container rules match the nearest ancestor */
.wrapper {
container-type: inline-size;
}
/* Named container — @container rules can target by name */
.page-layout {
container-type: inline-size;
container-name: layout;
}
/* Only targets the 'layout' container, not any inner container */
@container layout (min-width: 900px) {
.sidebar { width: 300px; }
}
Multiple names are allowed on a single element:
.card {
container-name: card panel widget;
container-type: inline-size;
}
container Shorthand
The container shorthand combines container-name and container-type in one declaration:
/* container: <name> / <type> */
.card-wrapper {
container: card / inline-size;
}
/* Multiple names */
.section {
container: section layout / inline-size;
}
@container Rule Syntax
The @container at-rule accepts an optional container name, then a condition in parentheses. The condition follows the same syntax as media query features.
/* Anonymous — targets the nearest container ancestor */
@container (min-width: 400px) { ... }
/* Named — targets a specific ancestor named 'card' */
@container card (min-width: 400px) { ... }
/* Logical operators */
@container (min-width: 400px) and (max-width: 800px) { ... }
@container card (min-width: 400px) or (max-width: 200px) { ... }
@container (not (min-width: 400px)) { ... }
Supported Container Features
| Feature | size | inline-size | Example |
|---|---|---|---|
width | ✓ | ✓ | (min-width: 400px) |
height | ✓ | — | (min-height: 200px) |
inline-size | ✓ | ✓ | (min-inline-size: 400px) |
block-size | ✓ | — | (min-block-size: 200px) |
aspect-ratio | ✓ | — | (aspect-ratio > 1) |
orientation | ✓ | — | (orientation: landscape) |
Range Syntax
Container queries support the modern range syntax from Media Queries Level 4:
@container (width > 400px) { ... }
@container (400px < width < 800px) { ... }
@container (inline-size >= 600px) { ... }
Container Query Length Units
Container query length units work like viewport units (vw, vh) but are relative to the query container instead of the viewport. They are available inside any @container rule.
| Unit | Full Name | Description | Available for |
|---|---|---|---|
cqw | Container Query Width | 1% of container’s width | size, inline-size |
cqh | Container Query Height | 1% of container’s height | size only |
cqi | Container Query Inline | 1% of container’s inline size | size, inline-size |
cqb | Container Query Block | 1% of container’s block size | size only |
cqmin | Container Query Min | Smaller of cqi or cqb | size only |
cqmax | Container Query Max | Larger of cqi or cqb | size only |
.container {
container-type: inline-size;
}
/* Font scales with container width, not viewport */
.heading {
font-size: clamp(1rem, 5cqi, 3rem);
}
/* Padding relative to container */
.card-body {
padding: 4cqw 6cqw;
}
cqi is generally preferred over cqw because it is writing-mode aware: in a vertical writing mode, cqi follows the inline axis (which is vertical), while cqw always refers to the physical width.
Style Queries (@container style())
Style queries let you apply styles based on the computed value of a CSS property on a container — most practically, custom properties (CSS variables). This makes it possible to build variant-driven design systems without JavaScript.
/* Set custom property on a parent */
.card[data-variant="primary"] {
--variant: primary;
container-type: normal;
container-name: card;
}
/* Query responds to the custom property */
@container card style(--variant: primary) {
.card-cta {
background: hsl(220, 90%, 56%);
color: white;
}
}
@container card style(--variant: danger) {
.card-cta {
background: hsl(0, 80%, 54%);
color: white;
}
}
Style queries can be combined with size conditions:
@container card (min-width: 400px) and style(--variant: primary) {
.card-layout { display: flex; }
}
Current limitation: As of 2025, style queries are limited to custom properties. Querying standard computed values like color or font-size is part of the specification but not yet supported in browsers.
Nested Containers
Containers can be nested. Each @container rule targets the nearest matching ancestor container by default, or a specific container if a name is provided.
/* Outer container — the full page layout */
.page {
container: page / inline-size;
}
/* Inner container — each card creates its own context */
.card {
container: card / inline-size;
}
/* Targets the nearest 'card' ancestor */
@container card (min-width: 300px) {
.card-body {
display: grid;
grid-template-columns: auto 1fr;
}
}
/* Targets the 'page' container regardless of depth */
@container page (min-width: 1200px) {
.card {
grid-column: span 2;
}
}
Rules for targeting:
- If no name is specified, the rule targets the nearest ancestor with an eligible container type.
- If a name is specified, the rule targets the nearest ancestor with that exact name.
- If no matching ancestor exists, the styles inside the
@containerblock are never applied.
Container Queries vs. Media Queries
| Container Queries | Media Queries | |
|---|---|---|
| Responds to | Container element size | Viewport size |
| Best for | Reusable components | Page-level layout |
| Multiple instances | Each adapts independently | All react identically |
| Requires | container-type on parent | Nothing |
| Support | Chrome/Firefox/Safari 2022+ | Universal |
Use container queries for components and media queries for page-level layout. They complement each other:
/* Media query controls the overall grid */
@media (min-width: 768px) {
.grid { grid-template-columns: 1fr 2fr; }
}
/* Container query controls how cards adapt to their column width */
.card-wrapper { container: card / inline-size; }
@container card (min-width: 400px) {
.card { flex-direction: row; }
}
Browser Support
Container queries for size and inline-size are supported in all modern browsers since late 2022. Style queries have slightly newer support.
| Feature | Chrome | Firefox | Safari | Edge |
|---|---|---|---|---|
| Size / inline-size queries | 105+ | 110+ | 16.0+ | 105+ |
| Container query units | 105+ | 110+ | 16.0+ | 105+ |
| Nested containers | 105+ | 110+ | 16.0+ | 105+ |
| Style queries | 111+ | 128+ | 18.0+ | 111+ |
For older browser support, you can use a polyfill (@oddbird/css-containers) or apply a safe fallback by writing default styles first and using container queries as progressive enhancement.
Frequently Asked Questions
Do I need to set a width on the container element?
No. The container element can have width: 100% or be block-level — it just needs container-type set. The browser measures the element’s computed inline size (or block size for size) to evaluate the query.
Why isn’t my @container query being applied?
Common causes: (1) The container ancestor doesn’t have container-type set. (2) You are querying the container element itself rather than its descendants — styles inside @container only apply to elements inside the container. (3) The container name doesn’t match.
Can I use container queries without a name?
Yes. An unnamed @container targets the nearest ancestor with an eligible container type. Named containers are only needed when you have nested containers and need to target a specific outer ancestor.
Can an element be both a grid item and a container?
Yes. An element can be a grid or flex child and also declare container-type. This is the typical pattern: the layout mechanism (grid) controls column widths, and the container query responds to those widths.
Do container queries work in Shadow DOM? Yes. Container queries work across shadow boundaries. A container established in light DOM can be queried from within a shadow root’s styles if the query selects elements inside the container.
What is the difference between cqw and cqi?
cqw always refers to the physical width of the container, while cqi refers to the inline-size axis which respects the writing mode. In horizontal left-to-right text, they are the same. In a vertical writing mode (writing-mode: vertical-rl), cqi follows the vertical axis. Prefer cqi for writing-mode-aware designs.