Contact

CSS Container Queries: The Responsive Design Feature We've Been Waiting For

November 25, 2025
Nick Paolini
5 min read
CSSResponsive DesignWeb Development
CSS Container Queries: The Responsive Design Feature We've Been Waiting For

For years, we've been stuck with media queries that respond to the viewport size. But what if your component needs to look different based on its container's size, not the whole screen? That's where container queries come in, and they're finally ready for production.

The Problem with Media Queries

Media queries work great for page-level layouts, but they fall apart when you have reusable components. Consider a card component:

.card {
  display: flex;
  flex-direction: column;
}
 
/* This breaks if the card is in a narrow sidebar! */
@media (min-width: 768px) {
  .card {
    flex-direction: row;
  }
}

The card switches to horizontal layout based on the viewport width, not its actual available space. If you put this card in a narrow sidebar, it'll still try to go horizontal on wide screens, even when there's no room.

Enter Container Queries

Container queries let components respond to their parent container's size instead:

.card-container {
  container-type: inline-size;
  container-name: card;
}
 
.card {
  display: flex;
  flex-direction: column;
}
 
@container card (min-width: 400px) {
  .card {
    flex-direction: row;
  }
}

Now the card only goes horizontal when its container is at least 400px wide. Put it in a sidebar? It stays vertical. Put it in the main content area? It goes horizontal. Perfect!

Real-World Example: A Product Card

Here's a practical example I built recently:

.product-grid {
  container-type: inline-size;
  display: grid;
  gap: 1rem;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
}
 
.product-card {
  display: grid;
  gap: 0.5rem;
  padding: 1rem;
  background: white;
  border-radius: 8px;
}
 
/* Compact layout for small containers */
.product-card img {
  width: 100%;
  aspect-ratio: 1;
  object-fit: cover;
}
 
.product-card h3 {
  font-size: 1rem;
}
 
.product-card .price {
  font-size: 1.25rem;
  font-weight: bold;
}
 
/* Enhanced layout when there's more space */
@container (min-width: 350px) {
  .product-card {
    grid-template-columns: 120px 1fr;
    grid-template-rows: auto auto 1fr auto;
    gap: 1rem;
  }
 
  .product-card img {
    grid-row: 1 / -1;
    height: 100%;
  }
 
  .product-card h3 {
    font-size: 1.125rem;
  }
}
 
/* Premium layout for larger containers */
@container (min-width: 500px) {
  .product-card {
    grid-template-columns: 200px 1fr;
  }
 
  .product-card img {
    aspect-ratio: 4/5;
  }
 
  .product-card h3 {
    font-size: 1.5rem;
  }
 
  .product-card .price {
    font-size: 1.5rem;
  }
}

The same component automatically adapts whether it's in a full-width grid, a sidebar, or a modal dialog. No JavaScript, no component props, just pure CSS.

Container Query Units

Container queries also introduce new units:

  • cqw - 1% of container width
  • cqh - 1% of container height
  • cqi - 1% of container inline size
  • cqb - 1% of container block size
  • cqmin - smaller of cqi or cqb
  • cqmax - larger of cqi or cqb

This lets you size things relative to the container:

.card-container {
  container-type: inline-size;
}
 
.card h2 {
  /* Font size scales with container width */
  font-size: clamp(1rem, 5cqw, 2rem);
}
 
.card .icon {
  /* Icon size relative to container */
  width: 10cqi;
  height: 10cqi;
}

Browser Support

The best part? Container queries are supported in all modern browsers:

  • Chrome 105+
  • Safari 16+
  • Firefox 110+
  • Edge 105+

That's about 90% of users globally. For the remaining 10%, the components just use their default (mobile) layout, which is a perfectly acceptable fallback.

Practical Tips

1. Name Your Containers

Give containers meaningful names to make your code more readable:

.sidebar {
  container-type: inline-size;
  container-name: sidebar;
}
 
@container sidebar (min-width: 300px) {
  /* Styles */
}

2. Container Type Matters

  • inline-size - Most common, queries container width
  • size - Queries both width and height (use sparingly, can cause layout issues)
  • normal - Default, no container queries

3. Combine with CSS Grid

Container queries + CSS Grid = chef's kiss

.layout {
  display: grid;
  gap: 2rem;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
}
 
.layout > * {
  container-type: inline-size;
}

Each grid item becomes a container, and child components respond to their actual size.

What I'm Building With It

I've been refactoring my component library to use container queries everywhere. Some highlights:

  • Navigation menus that switch between horizontal and vertical based on available space
  • Data tables that progressively hide columns in narrow containers
  • Form layouts that adapt from single-column to multi-column
  • Card grids that show different amounts of information based on card size

The Future is Bright

Container queries fundamentally change how we think about responsive design. Instead of designing for viewport breakpoints, we design components that adapt to any context.

This is huge for:

  • Design systems and component libraries
  • Third-party widgets and embeds
  • Micro-frontends
  • Any reusable UI component

If you haven't tried container queries yet, start with a simple card component. You'll immediately see why this is such a game-changer.

Resources

Have you used container queries in production yet? What's your favorite use case?