Skip to main content

A Practical Guide to CSS Container Queries

For years, media queries were the go-to tool for responsive design. They work great for layout changes based on the viewport, but they fall short when a component needs to look different depending on where it’s placed. That’s where CSS container queries come in.

Container queries allow an element to respond to the size of its parent container rather than the size of the browser window. This shift from page-level responsive design to component-level responsive design is a big deal for building design systems and reusable UI libraries.

Why Container Queries Matter

Imagine a card component. On a wide page it might sit in a three-column grid and look fine as a vertical card. But the same card dropped into a narrow sidebar suddenly feels cramped. With media queries, the card has no idea it’s inside a sidebar; it only sees the viewport width. Container queries solve this by letting the card observe its own container and adapt accordingly.

The result is components that are truly self-contained. You can drop them anywhere, and they just work.

Getting Started with Container Queries

To use container queries, you first need to define a containment context on a parent element. You do this with the container-type property.

.card-grid {
  container-type: inline-size;
}

The most common value is inline-size, which means the container will expose its inline size (width in horizontal writing modes) to its children. Once a container context is established, you can use the @container at-rule inside child elements.

.card {
  padding: 1rem;
  display: flex;
  flex-direction: column;
}

@container (min-width: 300px) {
  .card {
    flex-direction: row;
    align-items: center;
    gap: 1rem;
  }
}

Now, whenever a .card is inside a container that is at least 300px wide, it will switch to a horizontal layout.

Naming Your Containers

When you have multiple nested containers, things can get confusing. That’s why CSS lets you name containers with container-name.

.sidebar {
  container-type: inline-size;
  container-name: sidebar;
}

.main-content {
  container-type: inline-size;
  container-name: main;
}

Then in your query you can target a specific container by name.

@container sidebar (min-width: 250px) {
  .widget {
    font-size: 0.875rem;
  }
}

This keeps your styles predictable, especially in larger codebases.

A Real-World Example

Let’s say you have a product card that you use in both a main grid and a sidebar.

<div class="product-list">
  <article class="product-card">…</article>
</div>

<aside class="sidebar">
  <article class="product-card">…</article>
</aside>
.product-list,
.sidebar {
  container-type: inline-size;
}

.product-card {
  display: grid;
  gap: 0.5rem;
}

@container (min-width: 400px) {
  .product-card {
    grid-template-columns: 120px 1fr;
  }
}

The same .product-card now lays out differently based on whether it lives in the wide product list or the narrow sidebar. No extra classes, no breakpoint guessing.

Container Query Units

Container queries also introduce new length units that are relative to the container’s size:

  • 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

These are useful for fluid typography or sizing elements relative to the container rather than the viewport.

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

Browser Support and Fallbacks

Container queries are supported in all modern browsers, including Chrome, Edge, Firefox, and Safari. If you need to support older browsers, you can treat container queries as a progressive enhancement. Browsers that don’t understand @container will simply ignore it, so make sure the base styles are usable on their own.

For more critical layouts, you can pair container queries with feature queries.

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

@supports (container-type: inline-size) {
  .card-grid {
    container-type: inline-size;
  }

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

Final Thoughts

CSS container queries move responsive design closer to where it should have been all along: at the component level. Instead of asking “how wide is the viewport?” you can ask “how wide is my container?” That small change makes your components more reusable, your media queries fewer, and your design system more robust.

If you haven’t tried container queries yet, pick one reusable component in your project and convert it. You’ll be surprised how much cleaner your CSS becomes.