Container Queries: Components That Fit Their Container, Not the Screen
The dirty secret of media-query responsive design: a component doesn't care how wide the screen is - it cares how wide its slot is. The same product card renders in a 300px sidebar and a 900px main column on the same screen, and one media query can't serve both. We papered over this with .card--compact modifier classes for a decade.
.card-slot {
container-type: inline-size; /* make this element a measurable container */
}
.card {
display: grid;
gap: 12px;
}
@container (min-width: 420px) {
.card {
grid-template-columns: 140px 1fr; /* image beside text when there's room */
}
.card h3 { font-size: 1.25rem; }
}
Now the card checks the width of its nearest container ancestor. Sidebar instance stays stacked, main-column instance goes horizontal - same class, same stylesheet, zero JavaScript, zero modifier props threading through your templates.
The rules of the game
- Something must opt in: queries measure the nearest ancestor with container-type set. inline-size (width-only) is what you want 99% of the time - measuring block-size has chicken-and-egg problems with content height.
- The container can't style itself from its own query - only descendants. That's why the pattern is a thin wrapper (.card-slot) around the component, or making your existing grid cells the containers.
- Name containers when nesting:
container: sidebar / inline-size;then@container sidebar (min-width: ...)targets it explicitly instead of the nearest.
Container units: the underused half
.card h3 {
font-size: clamp(1rem, 4cqi, 1.5rem); /* scales with CONTAINER width */
}
cqi/cqw/cqb units are percentages of the container's size - fluid typography that tracks the slot, not the viewport. Combined with clamp(), component text sizes itself sensibly wherever the component lands.
Where media queries still win
Page-level layout (how many columns does the shell have), anything tied to the device itself (hover capability, motion preferences, print). The division of labor that's emerged in my projects: media queries arrange the page, container queries arrange the components. Both, not either.
Support: Chrome 105+, Safari 16+, Firefox 110+ - comfortably universal since early 2023. If you're building any kind of reusable card/widget/panel and still switching its layout with modifier classes, this is the feature you were waiting for, and it's been here a while.
Full-stack web developer sharing practical tutorials and building tools that ship.
Got something on your mind?
My inbox is open - no forms disappearing into the void here.
- Just say hello Found a tutorial useful? Spotted a mistake? Tell me.
- Hire me for a project Have something custom in mind? Let's talk scope and timelines.
- Product support Bought something here? I'll help you get it running.
I usually reply within 1-2 business days.