📦 Responsive Components, Not Just Pages
Media queries check viewport width. Component in sidebar? Full width? Same breakpoint fails. Container queries check parent width.
The Problem with Media Queries
❌ Media Queries
/* Card component */
.card {
display: flex;
}
@media (max-width: 768px) {
.card {
flex-direction: column; /* Stack on mobile */
}
}
Problem:
- Card in sidebar (300px): Still horizontal! (viewport > 768px)
- Card full width (800px): Stacked! (viewport < 768px)
- Component doesn't know its own width
Container Queries Solution
✅ Container Queries
/* Define container */
.sidebar,
.main-content {
container-type: inline-size;
container-name: card-container;
}
/* Card adapts to parent width */
.card {
display: flex;
}
@container card-container (max-width: 400px) {
.card {
flex-direction: column;
}
}
Result:
- Card in 300px sidebar: Stacked ✓
- Card in 800px main: Horizontal ✓
- Component responds to ITS container, not viewport
Real Example: Product Card
/* Container setup */
.product-grid {
container-type: inline-size;
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
gap: 1rem;
}
/* Card base style */
.product-card {
display: grid;
grid-template-areas:
"image"
"title"
"price"
"button";
}
/* When container > 300px: Horizontal layout */
@container (min-width: 300px) {
.product-card {
grid-template-areas:
"image title"
"image price"
"image button";
grid-template-columns: 120px 1fr;
}
}
/* When container > 500px: Full horizontal */
@container (min-width: 500px) {
.product-card {
grid-template-areas: "image title price button";
grid-template-columns: 150px 1fr auto auto;
align-items: center;
}
}
🎯 Container Query Units
| Unit | Meaning |
|---|---|
| cqw | 1% of container width |
| cqh | 1% of container height |
| cqi | 1% of container inline size |
| cqb | 1% of container block size |
/* Font size scales with container */
.card h2 {
font-size: clamp(1rem, 5cqw, 2rem);
}
/* Padding relative to container */
.card {
padding: 2cqi;
}
✅ When to Use Container Queries
- Reusable components: Card, panel, widget in different contexts
- Grid layouts: Items adapt to available space
- Sidebar vs main: Same component, different widths
- Design systems: Components work anywhere
⚠️ Browser Support
Current: 91% (Chrome 105+, Safari 16+, Firefox 110+)
Fallback: Use @supports to detect support
@supports (container-type: inline-size) {
/* Container query styles */
}
/* Fallback for older browsers */
@media (max-width: 768px) {
/* Media query fallback */
}
"Rebuilt our component library with container queries. Same card component works perfectly in sidebar, grid, full-width. No more variant props for different layouts. True responsive components."
