Lesson 6 of 30
A media query only ever knows about the viewport. Container queries let a component react to the space its actual parent gives it — a sidebar vs. a full-width section — which is what finally makes a truly reusable component possible.
13 min read
Every option explains itself — why the right one is right, and why each wrong one is wrong. Miss one and it comes back later on a spaced-repetition schedule.
Question 1 of 3
What's the fundamental difference between a media query and a container query?
Hints without spoilers, and a plain explanation of why a wrong answer was wrong — answered only from this lesson. Free account, no card.
Sign up freeWhat interviewers actually ask about this, and what a strong answer has to cover.
A strong answer covers
Likely follow-ups
A media query answers one question: how big is the browser window? That's fine for page-level decisions — collapsing a nav, switching a page grid from three columns to one — but it breaks down the moment you try to reuse a component in more than one place. A card that looks right in a full-width section will often look cramped or awkward dropped into a narrow sidebar, and a media query can't tell the difference, because both live inside the same viewport width.
A container query answers a different question: how big is this element's nearest ancestor that's been marked as a container? That's the shift. Instead of "how wide is the screen," the question becomes "how much space did my parent actually give me right now," which is exactly the information a reusable component needs to adapt itself, regardless of where it's dropped.
Two pieces make it work:
container-type on the parent — set to inline-size to say "let descendants query this element's width."@container on the component's own styles — a block that only applies when the nearest queryable ancestor matches a size condition, the same min-width/max-width syntax @media uses, just scoped to a container instead of the viewport..card-container {
container-type: inline-size;
container-name: card;
}
.card {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
@container card (min-width: 400px) {
.card {
flex-direction: row;
align-items: center;
gap: 1rem;
}
}
The same card component, dropped into two different parents: a narrow sidebar and a wide section.
The .card component itself never checks the viewport. It only knows: "if whatever wraps me is at least 400px wide, lay out horizontally; otherwise stack." Drop that exact same card into a 260px sidebar and it stacks. Drop it into a wide content section and it lays out as a horizontal row with an image and text side by side — same component, same CSS, zero JavaScript, zero duplicate markup per context. Before this existed, getting this behavior meant a ResizeObserver in JavaScript measuring the parent element and toggling a class, which is more code, more runtime cost, and one more thing that can desync from the CSS it's driving.
container-type: inline-size on .card-container lets its descendants query it — .card-container itself can't write an @container rule that reacts to its own size, since it's the thing being measured, not the thing doing the measuring.container-type: inline-size isn't free — it establishes containment, which affects how that element's children calculate percentage-based sizes in some edge cases and blocks things like break-inside in expected ways. It's rarely a practical problem for typical component layouts, but it's a real change to the box, not just a query capability.cqw, cqi, cqh) are less consistently supported, so check @supports for those specifically rather than assuming everything under the "container query" umbrella lands at the same time.@media; container queries are for how an individual component behaves once it's already been placed somewhere."How would you make a card component render differently depending on where it's placed, without JavaScript?" is a real question testing whether a candidate has moved past viewport-only thinking — reaching for container-type and @container instead of a ResizeObserver or a prop-drilled layout flag is the modern, expected answer.