• _hello
  • _about-me
  • _projects
  • _blog
  • _support
_contact-me
find me in:
@faeztgh
cd ../blog~/blog/css-container-queries
  • CSS
  • Frontend
  • Responsive Design

CSS Container Queries: Components That Own Their Responsiveness

Container queries let a component respond to the size of its container instead of the viewport. Here's how they work, the syntax, container query units, and why they change component design.

FFaez Tgh·Jul 4, 20265 min read·1,035 words
// share: post linkedin
Lines of layout and styling code on a screen

For over a decade, responsive design meant one thing: media queries that react to the viewport. That worked because layout was mostly a page-level concern. But component-driven development broke the assumption. The same card might sit in a wide main column on one page and a narrow sidebar on another. With media queries, the card has no idea which — it only knows the screen size, which tells it nothing about the space it was actually given.

Container queries fix the mismatch. Instead of asking "how big is the viewport?", a component asks "how big is my container?" and styles itself accordingly. A card becomes genuinely portable: drop it anywhere and it adapts to the room it has, not to a screen dimension it can't see. They're now supported across all major browsers, so this is a technique you can reach for, not just read about.

The problem media queries can't solve#

Consider a product card with an image and some text. In a wide container you want them side by side; in a narrow one, stacked. With media queries you'd write something like "when the viewport is above 700px, go side-by-side." But that's a lie about what you actually care about. Put that same card in a narrow sidebar on a wide screen and it goes side-by-side in a cramped column — because the viewport is wide even though the card's space is not.

The card's layout depends on the card's width. Media queries can't express that. Container queries can.

The syntax#

Two steps. First, declare an element as a container so its descendants can query it:

css
.card-wrapper {
  container-type: inline-size;
  container-name: card;
}

container-type: inline-size means "let children query my inline size" — width, in a normal horizontal writing mode. (size queries both dimensions but requires a fixed block size, so inline-size is what you want the vast majority of the time.) container-name is optional but makes intent clear when you have nested containers.

Then query that container with @container:

css
.card {
  display: flex;
  flex-direction: column;
}

@container card (min-width: 400px) {
  .card {
    flex-direction: row;
  }
}

Now the card stacks below 400px of container width and goes horizontal above it — regardless of the viewport. Move it between a wide column and a narrow sidebar and each instance does the right thing, from the same CSS.

Container query units#

Container queries bring their own relative units, sized against the query container rather than the viewport:

  • cqw — 1% of the container's width
  • cqh — 1% of the container's height
  • cqi — 1% of the container's inline size
  • cqb — 1% of the container's block size
  • cqmin / cqmax — the smaller / larger of cqi and cqb

These are the container-scoped cousins of vw/vh. Fluid typography that scales with the component's own width, for instance:

css
.card-title {
  font-size: clamp(1rem, 5cqi, 1.5rem);
}

The title grows with the card, not the window — so a card in a narrow slot keeps a sensible title size even on a huge monitor.

A mental shift, not just a feature#

The real change container queries bring isn't syntactic — it's architectural. They complete the promise of component-based UI. A component can now be fully self-contained: its structure, its behavior, and its responsiveness all travel with it. You can lift a card out of a page and drop it into a design-system catalog, a sidebar, or a modal, and it adapts everywhere without the parent having to know or the component having to guess about the viewport.

That's a cleaner boundary. The parent decides how much space to give a component; the component decides what to do with that space. Neither needs to know the other's internals.

Practical notes#

  • Reach for inline-size. True two-dimensional (size) queries need the container to have a definite block size, which is often awkward. Width-based queries cover almost every real case.
  • Mind the containment cost. Declaring container-type establishes size containment on that element, which can affect how it sizes itself — wrap the container around your component rather than putting container-type directly on an element whose intrinsic sizing you depend on.
  • They complement media queries, not replace them. Viewport-level concerns — overall page grid, showing or hiding a nav — are still media-query territory. Use container queries for component-level adaptation and media queries for page-level layout.
  • Style queries are the next step. The spec also allows querying a container's styles (like a custom property's value), opening the door to variant theming without extra class plumbing — worth watching as support matures.

The takeaway#

Media queries answer "how big is the screen?" Container queries answer "how big is the space this component was given?" — which is almost always the question a component actually needs answered. They turn responsive design from a page-level chore into a property a component carries with it, and they make truly reusable, context-agnostic components possible. If you build in components, this is one of the highest-value additions to CSS in years.

FAQ#

What's the difference between a container query and a media query?#

A media query responds to the viewport (the browser window), while a container query responds to the size of a specified ancestor container. Container queries let a component adapt to the actual space it's placed in, so the same component behaves correctly in a wide column or a narrow sidebar regardless of screen size.

What does container-type: inline-size do?#

It marks an element as a query container whose children can respond to its inline size (its width, in a standard horizontal layout). It's the option you want in almost all cases; container-type: size queries both dimensions but requires the container to have a definite height.

What are cqi, cqw, and the other container query units?#

They're relative units measured against the query container instead of the viewport: cqw is 1% of the container's width, cqi is 1% of its inline size, cqb/cqh are the block/height equivalents, and cqmin/cqmax are the smaller/larger of the inline and block sizes. They enable typography and spacing that scale with the component's own dimensions.

Do container queries replace media queries?#

No — they complement each other. Use container queries for component-level responsiveness and media queries for page-level concerns like the overall grid or global navigation. Both are widely supported across modern browsers.

References:

  • MDN — CSS container queries
  • web.dev — Container queries

#on this page

  • The problem media queries can't solve
  • The syntax
  • Container query units
  • A mental shift, not just a feature
  • Practical notes
  • The takeaway
  • FAQ
  • What's the difference between a container query and a media query?
  • What does container-type: inline-size do?
  • What are cqi, cqw, and the other container query units?
  • Do container queries replace media queries?
Discriminated Unions: TypeScript's Best Modelling Tool olderGetting Structured Output From LLMs Without the Guessworknewer