CSS Container Queries Cheat Sheet
Syntax for container-type, container-name, and @container rules to style elements based on their parent container's size.
Declaring a Containment Context
Mark an element as a query container so its children can respond to its size.
.card-wrapper { container-type: inline-size; /* query on width only, most common */ container-name: card; /* optional, lets you target it by name */}/* shorthand for both properties */.sidebar { container: sidebar / inline-size;}
@container Rule
Apply styles when the nearest queried ancestor container crosses a width threshold.
@container card (min-width: 400px) { .card-title { font-size: 1.5rem; grid-template-columns: 1fr 2fr; }}@container (max-width: 399px) { .card-title { font-size: 1rem; }}
Container Query Length Units
Size elements relative to the container instead of the viewport.
.card-icon { /* cqw/cqh = 1% of container's inline/block size */ width: 10cqw; /* cqi/cqb = logical inline/block equivalents */ padding: 2cqi; /* cqmin/cqmax = smaller/larger of cqi and cqb */ font-size: clamp(1rem, 4cqmin, 2rem);}
Container Style Queries
Query a custom property's value on the container, not just its size.
.theme-container { container-type: inline-size; --card-variant: compact;}@container style(--card-variant: compact) { .card { padding: 0.5rem; }}
Container Query Property Reference
The full set of properties/units involved.
- container-type- 'normal' | 'inline-size' | 'size' — size containment axis
- container-name- custom identifier used to target a specific ancestor in @container
- container (shorthand)- `name / type` combined, e.g. `sidebar / inline-size`
- cqw / cqh- 1% of the query container's width/height
- cqi / cqb- 1% of the container's inline-size/block-size (writing-mode aware)
- cqmin / cqmax- smaller/larger of cqi and cqb, handy for fluid typography
Targeting a Specific Ancestor with Nested Containers
When containers nest, use container-name so a rule queries the intended ancestor instead of the nearest one.
.page-layout { container: layout / inline-size;}.card-wrapper { container: card / inline-size; /* nested inside .page-layout */}/* targets the nearest ancestor named "card", skipping past "layout" */@container card (min-width: 300px) { .card-title { font-size: 1.25rem; }}/* explicitly reach the outer container by name */@container layout (min-width: 1000px) { .card-wrapper { grid-template-columns: repeat(3, 1fr); }}
Feature-Detecting with @supports
Ship a reasonable layout for browsers without container query support before progressively enhancing.
.card-title { font-size: 1rem; } /* safe fallback, applies everywhere */@supports (container-type: inline-size) { .card-wrapper { container-type: inline-size; } @container (min-width: 400px) { .card-title { font-size: 1.5rem; } }}
container-type: size for Block-Axis Queries
Query both width and height, but be aware size containment forces the container to ignore its children's intrinsic size.
.panel { /* must have an explicit height (or resize source) — size containment means children can no longer influence this element's own size */ container-type: size; height: 100dvh;}@container (min-height: 600px) and (min-width: 500px) { .panel .content { grid-template-rows: auto 1fr auto; }}
Compounding with :has() and Style Queries
Combine container size, a custom-property style query, and :has() for state-aware, size-aware component variants.
.toolbar { container: toolbar / inline-size;}@container toolbar (min-width: 480px) { .toolbar:has(.search-input:focus) .results-preview { display: block; }}@container style(--density: compact) and (min-width: 320px) { .toolbar-item { padding-block: 0.25rem; }}
Container Query Gotchas & Reference
Edge cases that trip people up once queries get nested or combined with other layout features.
- No self-querying- an element can never use a container-type set on itself; put container-type on the parent
- size containment side effect- container-type: size (or both axes) strips the element's intrinsic size contribution — you must give it an explicit dimension
- Nearest ancestor wins- an unnamed @container rule always targets the closest ancestor with container-type set, regardless of DOM depth
- container-name is not unique- multiple ancestors can share a name; the query still resolves to the nearest one carrying it
- No queries inside the queried element's own subtree loop- @container rules cannot create circular size dependencies (browser ignores contradictory cases)
- cqi/cqb vs cqw/cqh- prefer the logical units (cqi/cqb) for writing-mode-independent components; use cqw/cqh only for viewport-like fixed physical sizing
Set `container-type: inline-size` only on the direct parent you actually want to query from — an element can't query its own size, and setting `container-type` unnecessarily deep in the tree creates extra containment contexts that hurt layout performance.