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 widthcqh— 1% of container heightcqi— 1% of container inline sizecqb— 1% of container block sizecqmin— smaller ofcqiandcqbcqmax— larger ofcqiandcqb
.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.
Related Insights

Authentication Patterns in Modern Web Apps: JWT, Sessions, and Passkeys
A guide to modern authentication patterns comparing JWT, session-based auth, and passkeys including implementation strategies, security considerations, and user experience.

Code Splitting and Lazy Loading in React: Performance Optimization Guide
A comprehensive guide to code splitting and lazy loading in React applications including React.lazy, Suspense, route-based splitting, and component-level chunking.

CSS Grid vs Flexbox: Choosing the Right Layout System for Your Use Case
A comparison of CSS Grid and Flexbox layout systems including one-dimensional vs two-dimensional layouts, browser support, and use-case-specific recommendations.