Container Query Units: cqw, cqh, and cqi Explained
Container query units like cqw and cqi size elements relative to their containing element, not the viewport — here's how and when to use them.
Container query units are CSS length units — cqw, cqh, cqi, cqb, cqmin, and cqmax — that resolve relative to the size of a queried containing element instead of the viewport. Where vw always means “1% of the viewport width,” 1cqw means “1% of the nearest container’s width,” whatever that container happens to be. They’re the unit-level companion to CSS container queries: the query lets you branch on a container’s size, and the units let you scale a value smoothly with it.
What “container” means here
A container query unit only resolves against an element that has been made a query container — typically via container-type: inline-size (or size) on an ancestor, the same setup used for @container rules. Without a declared container, the units fall back to behaving like their small-viewport equivalents. That’s a deliberate fallback, not an error: it means a component authored with container units degrades gracefully if it’s ever dropped somewhere without a container ancestor, rather than throwing invalid values.
This is the core difference from media queries: a media query and viewport units only ever know about the whole browser window. Container query units know about whatever box you’ve opted into, which is what makes them useful for components that get reused in a sidebar, a modal, and a full-width section, each with a different available width.
The six units
| Unit | Resolves to |
|---|---|
cqw | 1% of the query container’s width |
cqh | 1% of the query container’s height |
cqi | 1% of the container’s inline size (width in horizontal writing modes) |
cqb | 1% of the container’s block size (height in horizontal writing modes) |
cqmin | The smaller of cqi and cqb |
cqmax | The larger of cqi and cqb |
In most left-to-right, top-to-bottom layouts, cqi and cqw are interchangeable, as are cqb and cqh. The logical units (cqi/cqb) are the better default because they keep working correctly if the writing mode changes — the same reason inline-size is generally preferred over width in modern CSS.
A practical example
A card component that scales its heading with the width of whatever container it’s placed in, rather than the viewport:
.card {
container-type: inline-size;
}
.card__title {
font-size: clamp(1rem, 4cqi, 2rem);
}
Drop that card into a 320px sidebar and the heading stays near 1rem. Drop the same markup into a 900px main column and it scales up toward 2rem — no media query breakpoints, no JavaScript ResizeObserver wiring, and no separate class for “sidebar card” versus “full-width card.” The clamp() pattern of a min, a fluid value, and a max works the same way it does with vw, just anchored to the container instead of the window.
Container units vs percentages
It’s tempting to reach for a plain percentage instead, but percentages and container query units solve different problems. A percentage on font-size or padding is relative to the computed value of the same property on the parent (or the containing block, depending on the property) — the rules are inconsistent across properties and don’t compose well with calc() for fluid scaling. A container query unit is always a straightforward percentage of the query container’s box, regardless of which CSS property you apply it to, which makes it far easier to reason about inside clamp() and calc() expressions.
Container units also don’t require the same ancestor to be a direct parent. Any descendant of a query container can use cqi/cqh, even several levels down, as long as no intervening element redeclares itself as a different query container (which would rescope the units to that closer ancestor instead).
Pairing with other container query features
Container query units are most useful alongside @container style queries and the layout tools built for the same use case:
- CSS subgrid for aligning nested grid tracks to a parent grid, so components sized with container units still line up.
:has()for styling a container based on what it contains, which often pairs naturally with sizing that container’s children bycqi.- Cascade layers for keeping container-query-based component styles cleanly separated from global resets and utility classes as a design system grows.
When not to use them
If a value genuinely should track the viewport — a full-bleed hero’s height, say — viewport units are still the right tool. Reach for container query units specifically when a component’s sizing should depend on the space it’s been given, not the window as a whole: dashboard widgets, card grids, sidebar-or-main layouts, and anything meant to be dropped into multiple contexts without a rewrite.
The takeaway
Container query units (cqw, cqh, cqi, cqb, cqmin, cqmax) let an element’s sizing track its containing element instead of the viewport, provided that container has opted in with container-type. Prefer the logical cqi/cqb pair for writing-mode-safe layouts, combine them with clamp() for fluid scaling, and reach for them any time a component needs to size itself to “however much space I’ve actually been given” rather than “however big the browser window is.”
Tagged
Keep reading
Takina · · 4 min read CSS Relative Color Syntax: Deriving Colors from Colors
Relative color syntax lets CSS derive a new color from an existing one by adjusting its channels directly, no preprocessor or JS required.
Takina · · 4 min read What Is CSS Subgrid? Nested Grid Alignment Explained
CSS subgrid lets a nested grid item inherit its parent's track sizing, so children can align to the same columns or rows across unrelated containers.
Takina · · 4 min read CSS field-sizing Property Explained
The CSS field-sizing property lets form controls like textareas grow to fit their content automatically, without JavaScript resize listeners.