CSS Container Queries Definitive Guide: The Ultimate Component-Level Responsive Design Solution
Container Queries: A Paradigm Shift in Responsive Design
Traditional media queries are based on viewport width, while container queries are based on parent container width — this seemingly small difference fundamentally transforms component reusability.
| Dimension | Media Queries | Container Queries |
|---|---|---|
| Reference | Viewport | Parent Container |
| Reusability | Component depends on page layout | Component is fully independent |
| Sidebar scenarios | Requires extra breakpoints | Auto-adapts |
| Nested components | Cannot sense parent | Natively supported |
| Browser support | All | Chrome 105+, Firefox 110+, Safari 16+ |
Basic Syntax
Defining a Container
.card-container {
container-type: inline-size;
container-name: card;
}
/* Shorthand */
.card-container {
container: card / inline-size;
}
container-type values:
| Value | Meaning | Queryable Dimensions |
|---|---|---|
inline-size |
Inline-axis container | Width |
size |
Dual-axis container | Width + Height |
normal |
Not a container (default) | None |
Writing Container Queries
@container card (min-width: 400px) {
.card {
flex-direction: row;
}
.card-title {
font-size: 1.5rem;
}
}
@container card (max-width: 399px) {
.card {
flex-direction: column;
}
.card-title {
font-size: 1.2rem;
}
}
Practical Example: Adaptive Card Component
HTML Structure
<div class="sidebar">
<div class="card-container">
<article class="card">
<img class="card-img" src="photo.jpg" alt="">
<div class="card-body">
<h3 class="card-title">Article Title</h3>
<p class="card-desc">Article excerpt content</p>
<span class="card-tag">Frontend</span>
</div>
</article>
</div>
</div>
<div class="main-content">
<div class="card-container">
<article class="card">
<!-- Same card component -->
</article>
</div>
</div>
CSS Implementation
.card-container {
container: card / inline-size;
}
.card {
display: flex;
flex-direction: column;
gap: 1rem;
padding: 1rem;
}
.card-img {
width: 100%;
aspect-ratio: 16 / 9;
object-fit: cover;
border-radius: 0.5rem;
}
/* Container width > 400px: Horizontal layout */
@container card (min-width: 400px) {
.card {
flex-direction: row;
align-items: center;
}
.card-img {
width: 200px;
aspect-ratio: 1;
flex-shrink: 0;
}
.card-title {
font-size: 1.25rem;
}
}
/* Container width > 600px: Large card layout */
@container card (min-width: 600px) {
.card-img {
width: 280px;
}
.card-title {
font-size: 1.5rem;
}
.card-desc {
-webkit-line-clamp: 3;
}
}
Result: The same .card component automatically displays vertically in a 300px sidebar and horizontally in a 700px main content area — without any media queries.
Container Query Units
Similar to vw/vh, but referencing the container instead of the viewport:
| Unit | Reference | Equivalence |
|---|---|---|
cqw |
1% of container width | 1cqw = container width × 1% |
cqh |
1% of container height | 1cqh = container height × 1% |
cqi |
1% of container inline size | Equals cqw (horizontal writing mode) |
cqb |
1% of container block size | Equals cqh (horizontal writing mode) |
cqmin |
min(cqi, cqb) | The smaller value |
cqmax |
max(cqi, cqb) | The larger value |
.card-title {
font-size: clamp(1rem, 3cqw, 2rem);
padding: 2cqw;
}
Practical Example: Responsive Navigation Bar
.nav-container {
container: nav / inline-size;
}
.nav {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
}
/* Narrow container: Hamburger menu */
@container nav (max-width: 500px) {
.nav-links {
display: none;
}
.nav-hamburger {
display: block;
}
}
/* Medium container: Horizontal navigation */
@container nav (min-width: 501px) {
.nav-links {
display: flex;
gap: 1rem;
}
.nav-hamburger {
display: none;
}
}
/* Wide container: Navigation + Search box */
@container nav (min-width: 800px) {
.nav-search {
display: flex;
}
}
Synergy with Media Queries
Container queries don't replace media queries — they divide responsibilities:
/* Media queries: Handle page-level layout */
@media (min-width: 1024px) {
.layout {
grid-template-columns: 280px 1fr;
}
}
/* Container queries: Handle component-level layout */
@container card (min-width: 400px) {
.card {
flex-direction: row;
}
}
| Scenario | Use |
|---|---|
| Page overall layout switching | Media queries |
| Component internal adaptation | Container queries |
| Global font scaling | Media queries |
| Component text scaling with container | Container query units |
Container Style Queries
CSS Container Query Level 3 introduces style queries, which can switch styles based on container custom property values:
.card-container {
container-type: inline-size;
--theme: light;
}
.card-container.dark {
--theme: dark;
}
@container style(--theme: dark) {
.card {
background: #1a1a2e;
color: #e0e0e0;
}
}
@container style(--theme: light) {
.card {
background: #ffffff;
color: #333333;
}
}
Performance Optimization
Avoid Excessive Nesting
/* Not recommended: Multiple nested containers */
.outer { container: outer / inline-size; }
.middle { container: middle / inline-size; }
.inner { container: inner / inline-size; }
/* Recommended: Set containers only at levels that need adaptation */
.card-wrapper { container: card / inline-size; }
Container Size Calculation
Container query size calculation excludes child element overflow but includes padding and border. Set box-sizing: border-box for consistent behavior.
Fallback Strategy
/* Base styles: Mobile-first */
.card {
flex-direction: column;
}
/* Container query enhancement */
@supports (container-type: inline-size) {
.card-container {
container: card / inline-size;
}
@container card (min-width: 400px) {
.card {
flex-direction: row;
}
}
}
/* Media query fallback when unsupported */
@supports not (container-type: inline-size) {
@media (min-width: 768px) {
.card {
flex-direction: row;
}
}
}
Browser Compatibility (2026)
| Browser | Container Queries | Container Query Units | Style Queries |
|---|---|---|---|
| Chrome 105+ | ✅ | ✅ | ✅ (117+) |
| Firefox 110+ | ✅ | ✅ | ❌ |
| Safari 16+ | ✅ | ✅ | ✅ (17+) |
| Edge 105+ | ✅ | ✅ | ✅ |
Conclusion: Container queries have full support across mainstream browsers and can be used confidently in production. Style queries, as an enhancement, are recommended for progressive adoption with @supports.
Try these browser-local tools — no sign-up required →