CSS Container Queries: Building Truly Responsive Components | SoniNow Blog

Limited TimeLearn More

csscontainer queriesresponsive designfrontendweb development

CSS Container Queries: Building Truly Responsive Components

Published

2026-06-23

Read Time

4 mins

CSS Container Queries: Building Truly Responsive Components

For over a decade, responsive design meant one thing: media queries that react to the viewport width. CSS Container Queries change this fundamentally by letting components respond to their own container's size. A card placed in a wide sidebar renders differently than the same card in a narrow column — without any JavaScript, props, or conditional rendering. Here is everything you need to know.

Container Query Fundamentals

Container queries require two steps: defining a containment context and writing the query. The container-type property establishes the container, and @container queries its size.

/* Step 1: Establish a containment context */
.card-grid {
  container-type: inline-size;
  container-name: grid;
}

/* Step 2: Query the container's inline size */
@container grid (min-width: 400px) {
  .card {
    display: grid;
    grid-template-columns: 200px 1fr;
    gap: 1rem;
  }
}

@container grid (min-width: 300px) and (max-width: 399px) {
  .card {
    display: flex;
    flex-direction: row;
    align-items: center;
  }
}

@container grid (max-width: 299px) {
  .card {
    display: flex;
    flex-direction: column;
  }
}

The magic is that @container queries the nearest ancestor with a containment context, not the viewport. Place the same card component in a 600px sidebar and a 300px modal, and it renders appropriately for each.

The Container Query Card Component

A practical example: a product card that shifts between horizontal and vertical layouts based on available space.

.product-grid {
  container-type: inline-size;
  container-name: product;
}

.product-card {
  display: flex;
  gap: 0.5rem;
  padding: 1rem;
  border-radius: 8px;
  background: var(--surface);
}

.product-card__image {
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  border-radius: 4px;
}

.product-card__title {
  font-size: clamp(0.875rem, 1.5cqi, 1.25rem);
  font-weight: 600;
}

@container product (min-width: 350px) {
  .product-card {
    flex-direction: row;
  }
  
  .product-card__image {
    width: 120px;
    height: 120px;
  }
}

@container product (max-width: 349px) {
  .product-card {
    flex-direction: column;
  }
  
  .product-card__image {
    width: 100%;
  }
}

Notice 1.5cqi — container query units. cqi (container query inline) scales relative to the container's inline size, keeping typography proportional to layout.

Container Query Units

Container queries introduce five new CSS 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 and cqb
  • cqmax — larger of cqi and cqb
.card-title {
  /* Fluid typography tied to container, not viewport */
  font-size: clamp(1rem, 3cqi, 2rem);
}

.card-icon {
  /* Icon scales with container */
  width: 5cqi;
  height: 5cqi;
}

These units eliminate the need for JavaScript-based text scaling or viewport-relative font sizes that break when components move between layouts.

Nested Containers and Performance

Containers can be nested, but each container query requires the browser to track that container's size. Deep nesting with dozens of container elements can impact layout performance. Keep these guidelines:

/* ✅ Good: one containment context per component boundary */
.card-wrapper {
  container-type: inline-size;
}

/* ❌ Avoid: unnecessary nested containment */
.wrapper {
  container-type: inline-size;
}
.inner {
  container-type: inline-size;  
}
.card {
  container-type: inline-size;
}

Use container queries at component boundaries — the grid that contains cards, the sidebar that contains widgets, the layout that contains panels. Do not add containment to every <div>.

Combining with Media Queries

Container queries and media queries serve different purposes. Media queries handle overall page layout — how many columns, sidebar visibility, header structure. Container queries handle internal component adaptation.

/* Page-level layout: media query */
@media (min-width: 768px) {
  .page-layout {
    display: grid;
    grid-template-columns: 300px 1fr;
  }
}

/* Component-level adaptation: container query */
@container sidebar (min-width: 250px) {
  .widget {
    display: grid;
    grid-template-columns: 1fr 1fr;
  }
}

This separation means your page layout and component layout concerns no longer share the same if-else chain.

Browser Support and Progressive Enhancement

Container queries are supported in all major browsers since 2023. For older browsers, provide a fallback layout that works without container queries — typically a flex column layout that degrades gracefully.

/* Fallback for unsupported browsers */
.card {
  display: flex;
  flex-direction: column;
}

/* Enhancement for browsers supporting container queries */
@supports (container-type: inline-size) {
  @container product (min-width: 350px) {
    .card {
      flex-direction: row;
    }
  }
}

True Component Responsiveness

Container queries complete the responsive design model that media queries started. Components become truly portable — the same React component renders correctly in any context because its layout responds to its own container, not a global viewport width.

At SoniNow, we build design systems with container query-driven components that adapt to any layout context. Our web development services include container query migration, design system implementation, and responsive architecture consulting.

Build components that adapt. Collaborate with SoniNow to implement container-aware responsive design.