Container Queries revolutionize responsive design by allowing components to adapt based on their container's size rather than just the viewport. This powerful feature enables truly modular and reusable components.
Understanding Container Queries
Container Queries allow elements to respond to their parent container's dimensions rather than the viewport size, enabling more flexible and reusable components.
Basic Setup
First, define a containment context:
.card-container {
container-type: inline-size;
container-name: card;
}
.card {
display: grid;
gap: 1rem;
padding: 1rem;
}
@container card (min-width: 400px) {
.card {
grid-template-columns: 200px 1fr;
}
}
Practical Examples
Responsive Product Card
Create a product card that adapts to its container:
.products-grid {
container-type: inline-size;
container-name: products;
display: grid;
gap: 1rem;
grid-template-columns: repeat(
auto-fit,
minmax(250px, 1fr)
);
}
.product-card {
display: grid;
gap: 1rem;
padding: 1.5rem;
border-radius: 8px;
background: #fff;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
@container products (min-width: 300px) {
.product-card {
grid-template-columns: 120px 1fr;
}
.product-image {
grid-row: span 2;
}
}
@container products (max-width: 299px) {
.product-card {
text-align: center;
}
.product-image {
margin: 0 auto;
max-width: 200px;
}
}
Adaptive Navigation
Create a navigation component that responds to its container:
.nav-container {
container-type: inline-size;
container-name: nav;
}
.nav-list {
display: flex;
gap: 1rem;
list-style: none;
padding: 0;
margin: 0;
}
@container nav (max-width: 600px) {
.nav-list {
flex-direction: column;
}
.nav-item {
padding: 0.5rem 0;
border-bottom: 1px solid #eee;
}
}
Advanced Container Query Patterns
Nested Containers
Implement nested container queries for complex layouts:
.page-layout {
container-type: inline-size;
container-name: page;
}
.sidebar {
container-type: inline-size;
container-name: sidebar;
}
.widget {
padding: 1rem;
background: #f8fafc;
}
@container page (min-width: 1200px) {
.layout-grid {
display: grid;
grid-template-columns: 300px 1fr;
gap: 2rem;
}
}
@container sidebar (min-width: 250px) {
.widget {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 1rem;
}
}
Component Library Integration
Create responsive components that work anywhere:
.component-wrapper {
container-type: inline-size;
container-name: component;
}
.flexible-component {
display: grid;
gap: 1rem;
}
@container component (min-width: 600px) {
.flexible-component {
grid-template-columns: repeat(2, 1fr);
}
}
@container component (min-width: 900px) {
.flexible-component {
grid-template-columns: repeat(3, 1fr);
}
}
Combining with Modern CSS Features
Using Container Queries with Grid
Create adaptive grid layouts:
.grid-container {
container-type: inline-size;
container-name: grid;
display: grid;
gap: 1rem;
}
@container grid (min-width: 400px) {
.grid-container {
grid-template-columns: repeat(
auto-fit,
minmax(180px, 1fr)
);
}
}
@container grid (min-width: 800px) {
.grid-container {
grid-template-columns: repeat(
auto-fit,
minmax(250px, 1fr)
);
}
}
Fluid Typography with Container Queries
Implement responsive typography:
.text-container {
container-type: inline-size;
container-name: text;
}
.adaptive-heading {
font-size: clamp(1.5rem, 5cqi, 3rem);
line-height: 1.2;
}
.adaptive-text {
font-size: clamp(1rem, 2.5cqi, 1.25rem);
line-height: 1.5;
}
Performance Considerations
Containment Optimization
Optimize rendering performance:
.optimized-container {
container-type: inline-size;
contain: layout style paint;
}
.scroll-container {
container-type: inline-size;
contain: content;
overflow-y: auto;
}
Loading Strategies
Implement progressive enhancement:
.component {
/* Base styles */
display: grid;
gap: 1rem;
}
@supports (container-type: inline-size) {
.component-wrapper {
container-type: inline-size;
}
@container (min-width: 400px) {
.component {
/* Enhanced layout */
grid-template-columns: repeat(2, 1fr);
}
}
}
Debugging and Testing
Debug Utilities
Create helper styles for development:
@media (min-width: 768px) {
.debug-container {
position: relative;
}
.debug-container::after {
content: attr(class) ' - ' attr(style);
position: absolute;
bottom: 100%;
left: 0;
font-size: 12px;
background: #333;
color: white;
padding: 2px 4px;
white-space: nowrap;
}
}
Testing Different Sizes
Create a test harness:
.test-wrapper {
resize: horizontal;
overflow: auto;
min-width: 200px;
max-width: 800px;
margin: 2rem auto;
padding: 1rem;
border: 2px dashed #ccc;
}
.size-indicator {
position: sticky;
top: 0;
background: #333;
color: white;
padding: 0.5rem;
text-align: center;
}
Best Practices
- Component Independence
- Design components to work at any size
- Use relative units (rem, em, %)
- Test components in different contexts
- Performance
- Use containment appropriately
- Minimize container query nesting
- Implement progressive enhancement
- Maintainability
- Use logical breakpoints
- Document container requirements
- Create reusable patterns
Browser Support and Fallbacks
Implement graceful degradation:
@supports not (container-type: inline-size) {
.fallback-layout {
display: grid;
grid-template-columns: repeat(
auto-fit,
minmax(250px, 1fr)
);
}
}
@supports (container-type: inline-size) {
.modern-layout {
container-type: inline-size;
}
@container (min-width: 400px) {
.modern-layout {
/* Modern styles */
}
}
}
Conclusion
Container Queries represent a significant advancement in responsive design:
- Component-level responsiveness
- Improved reusability
- More maintainable code
- Better component encapsulation
Key takeaways:
- Use container queries for component-level responsiveness
- Combine with other modern CSS features
- Consider performance implications
- Implement appropriate fallbacks
- Test thoroughly across different contexts
By mastering Container Queries, you can create truly responsive and reusable components that adapt beautifully to their containing context.