
CSS Container Queries: Responsive Components, Not Just Pages
Media queries transformed web design by making pages responsive. Container queries complete the revolution by making components responsive to their container, not the viewport.
The Problem with Media Queries
Media queries only respond to viewport size:
/* This card changes at viewport breakpoints */
@media (min-width: 768px) {
.card {
display: grid;
grid-template-columns: 200px 1fr;
}
} But what if the card is in a narrow sidebar? It still gets the “wide” layout because the viewport is wide, even though the card’s container is narrow.
Enter Container Queries
Container queries let components respond to their container’s size:
.sidebar {
container-type: inline-size;
container-name: sidebar;
}
@container sidebar (min-width: 400px) {
.card {
display: grid;
grid-template-columns: 200px 1fr;
}
} Now the card responds to the sidebar’s width, not the viewport!
Basic Setup
1. Define a Container
.container {
container-type: inline-size; /* Width queries */
/* or */
container-type: size; /* Width AND height queries */
/* or */
container-type: normal; /* Not a container */
} 2. Optionally Name It
.sidebar {
container-type: inline-size;
container-name: sidebar;
} 3. Query It
/* Query nearest container */
@container (min-width: 400px) {
.card {
/* styles */
}
}
/* Query named container */
@container sidebar (min-width: 400px) {
.card {
/* styles */
}
} Container Query Units
New units for sizing relative to containers:
cqw- 1% of container widthcqh- 1% of container heightcqi- 1% of container inline sizecqb- 1% of container block sizecqmin- Smaller ofcqiorcqbcqmax- Larger ofcqiorcqb
.card-title {
font-size: clamp(1rem, 5cqi, 3rem);
padding: 2cqi;
} Practical Use Cases
1. Responsive Card Component
.card-wrapper {
container-type: inline-size;
}
.card {
display: grid;
gap: 1rem;
padding: 1rem;
}
/* Horizontal layout when container is wide */
@container (min-width: 500px) {
.card {
grid-template-columns: 200px 1fr;
}
}
/* Even wider: add sidebar */
@container (min-width: 800px) {
.card {
grid-template-columns: 200px 1fr 150px;
}
} 2. Typography Scaling
article {
container-type: inline-size;
container-name: article;
}
@container article (min-width: 400px) {
h1 {
font-size: 2rem;
}
p {
font-size: 1rem;
}
}
@container article (min-width: 600px) {
h1 {
font-size: 2.5rem;
}
p {
font-size: 1.125rem;
}
}
@container article (min-width: 800px) {
h1 {
font-size: 3rem;
}
p {
font-size: 1.25rem;
}
} 3. Adaptive Navigation
nav {
container-type: inline-size;
}
/* Compact nav for narrow containers */
.nav-list {
display: flex;
flex-direction: column;
}
@container (min-width: 600px) {
.nav-list {
flex-direction: row;
gap: 2rem;
}
}
@container (min-width: 900px) {
.nav-item {
font-size: 1.125rem;
}
.nav-icon {
display: none; /* Hide icons when we have space */
}
} Advanced Techniques
Container Query Length Units
.product-grid {
container-type: inline-size;
}
.product-card {
/* Font size scales with container */
font-size: clamp(0.875rem, 2.5cqi, 1.25rem);
/* Padding relative to container */
padding: 3cqi;
/* Border radius relative to container */
border-radius: 2cqi;
} Nesting Container Queries
.page {
container-type: inline-size;
container-name: page;
}
.sidebar {
container-type: inline-size;
container-name: sidebar;
}
/* Query page container */
@container page (min-width: 1200px) {
.content {
max-width: 800px;
}
}
/* Query sidebar container */
@container sidebar (min-width: 300px) {
.widget {
padding: 2rem;
}
} Combining with Media Queries
/* Use media queries for page-level layout */
@media (min-width: 1024px) {
.layout {
display: grid;
grid-template-columns: 250px 1fr;
}
}
/* Use container queries for component-level adaptation */
@container (min-width: 500px) {
.card {
display: grid;
grid-template-columns: 1fr 1fr;
}
} Real-World Example: Product Card
.product-list {
container-type: inline-size;
display: grid;
gap: 1rem;
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
}
.product {
display: flex;
flex-direction: column;
gap: 1rem;
background: white;
border-radius: 8px;
padding: 1rem;
}
/* Small container: Stack everything */
.product-image {
aspect-ratio: 1;
}
@container (min-width: 300px) {
.product {
gap: 1.5rem;
padding: 1.5rem;
}
.product-title {
font-size: clamp(1rem, 4cqi, 1.5rem);
}
}
/* Medium container: Horizontal layout */
@container (min-width: 500px) {
.product {
flex-direction: row;
}
.product-image {
width: 40%;
flex-shrink: 0;
}
}
/* Large container: Add more details */
@container (min-width: 700px) {
.product-specs {
display: block; /* Show hidden specs */
}
.product-description {
-webkit-line-clamp: 4; /* Show more lines */
}
} Browser Support
Container queries have excellent modern browser support:
- Chrome/Edge: ✅ v105+ (September 2022)
- Firefox: ✅ v110+ (February 2023)
- Safari: ✅ v16+ (September 2022)
Global support is now ~90%, making it production-ready.
Progressive Enhancement
Provide fallbacks for older browsers:
/* Fallback layout */
.card {
display: block;
}
/* Enhanced layout with container queries */
@supports (container-type: inline-size) {
.card-container {
container-type: inline-size;
}
@container (min-width: 500px) {
.card {
display: grid;
grid-template-columns: 200px 1fr;
}
}
} Performance Considerations
- Container queries are performant - they’re native browser features
- Avoid excessive nesting - too many containers can be confusing
- Use named containers for clarity in complex layouts
Common Pitfalls
1. Forgetting container-type
/* ❌ Won't work - no container-type */
.wrapper {
}
@container (min-width: 400px) {
.child {
}
}
/* ✅ Correct */
.wrapper {
container-type: inline-size;
}
@container (min-width: 400px) {
.child {
}
} 2. Using size on Grid/Flex Containers
/* ⚠️ Can cause issues with flex/grid sizing */
.flex-container {
display: flex;
container-type: size; /* May cause layout issues */
}
/* ✅ Better - use inline-size */
.flex-container {
display: flex;
container-type: inline-size;
} 3. Circular Dependencies
/* ❌ Can't query the same element */
.container {
container-type: inline-size;
width: 100%;
}
@container (min-width: 500px) {
.container {
/* Can't style itself */
width: 600px;
}
} Combining with Other Modern CSS
Container Queries + Subgrid
.grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
container-type: inline-size;
}
.card {
display: grid;
grid-template-rows: subgrid;
grid-row: span 3;
}
@container (min-width: 300px) {
.card {
grid-row: span 4; /* Add extra row */
}
} Container Queries + :has()
.container {
container-type: inline-size;
}
/* Adjust layout when container has image */
@container (min-width: 500px) {
.card:has(img) {
grid-template-columns: 200px 1fr;
}
} When to Use Container Queries vs Media Queries
Use Container Queries:
- Component-level responsiveness
- Reusable components in different contexts
- Design systems and component libraries
- Cards, widgets, modals
Use Media Queries:
- Page-level layout changes
- Global styles (font-size on html)
- Multi-column layouts
- Navigation structure
Use Both:
/* Media query: page layout */
@media (min-width: 1024px) {
.page {
display: grid;
grid-template-columns: 300px 1fr;
}
}
/* Container query: component adaptation */
@container (min-width: 400px) {
.card {
display: flex;
gap: 2rem;
}
} Conclusion
Container queries represent a paradigm shift in responsive design. They enable truly modular, context-aware components that adapt to their environment rather than the viewport.
This is especially powerful for:
- Design systems
- Component libraries
- Micro-frontends
- Content management systems
Start using container queries today to build more resilient, adaptable interfaces.
Browser support snapshot
Live support matrix for css-container-queries from
Can I Use.
Show static fallback image

Source: caniuse.com









