Next: container queries: styling components based on the size of their parent container, not the viewport. Media queries answer ‘how wide is the screen?’; container queries answer ‘how wide is this card’s slot?’.
Defining a containment context
A parent becomes a query container with container-type or the shorthand container:
.card-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(16rem, 1fr));
gap: 1rem;
}
.card-slot {
container-type: inline-size;
/* shorthand: container: card / inline-size; */
}
inline-size tracks the width in horizontal writing mode (height in vertical writing mode). That is what you want for most layout decisions. size tracks both dimensions but requires explicit height on the container, which is rarer in practice.
@container rules
Inside the container’s descendants, use @container with a min or max width:
.card {
display: flex;
flex-direction: column;
gap: 0.75rem;
padding: 1rem;
}
@container (min-width: 28rem) {
.card {
flex-direction: row;
align-items: center;
}
.card__media {
flex: 0 0 120px;
}
}
The same .card component stacks vertically in a narrow sidebar and sits horizontally in a wide main column. One component, two layouts, no duplicate markup or modifier classes tied to page regions.
Named containers
When containers nest, name them so queries target the right ancestor:
.sidebar {
container: sidebar / inline-size;
}
.main {
container: main / inline-size;
}
@container sidebar (min-width: 20rem) {
.widget {
padding: 1.5rem;
}
}
@container main (min-width: 40rem) {
.widget {
display: grid;
grid-template-columns: 1fr 1fr;
}
}
Container query units
Length units relative to the container exist: cqi (1% of inline size), cqw, cqh, and others. Useful for fluid padding and type inside a component:
.stat {
container-type: inline-size;
padding: 2cqi;
}
.stat__value {
font-size: clamp(1.5rem, 4cqi + 0.5rem, 2.5rem);
}
Do not replace every rem with cqi. Use container units when the component should scale with its slot, not with the root font size alone.
Style queries (container-type: style)
Container queries can also match custom property values on the container:
.theme-box {
container-type: inline-size;
container-name: theme;
--variant: calm;
}
.theme-box[data-variant="loud"] {
--variant: loud;
}
@container theme style(--variant: loud) {
.theme-box__title {
text-transform: uppercase;
letter-spacing: 0.05em;
}
}
Style queries are newer and less universally needed than size queries. Handy when a parent sets a token and children branch on it without extra classes.
When to use media vs container queries
Use media queries for page-level decisions: navigation pattern, overall grid columns, whether the sidebar exists at all. Use container queries for reusable components: cards, media objects, data tables in a widget, article previews in a grid.
- Media query – ‘On small screens, hide the sidebar and show a menu button.’
- Container query – ‘When this card is wider than 28rem, put the image beside the text.’
HTML structure hint
The query container is often a wrapper around the component, not the component root itself:
<div class="card-slot">
<article class="card">
<img class="card__media" src="thumb.jpg" alt="">
<div class="card__body">…</div>
</article>
</div>
.card-slot establishes containment; .card holds the styles. That separation keeps the component ignorant of where it is placed.
The next tutorial covers fluid typography and spacing with clamp() and logical properties – scaling that feels natural from phone to desktop.

