Learn how container queries are revolutionizing responsive design, moving beyond media queries to create more flexible and maintainable CSS architectures.
Responsive design has been the cornerstone of modern web development for over a decade. Media queries have served us well, but they have limitations when it comes to creating truly component-driven responsive interfaces. Enter container queries—a game-changing CSS feature that’s revolutionizing how we approach responsive design.
Traditional media queries have served us well, but they come with inherent limitations:
/* Traditional media query approach */
.component {
width: 100%;
}
@media (min-width: 768px) {
.component {
width: 50%;
}
}
@media (min-width: 1024px) {
.component {
width: 33.333%;
}
}
Problems with this approach:
Container queries allow elements to respond to the size of their parent container rather than the viewport:
/* Modern container query approach */
.component {
width: 100%;
}
/* Create a container context */
.container {
container-type: inline-size;
}
/* Component responds to its container's size */
@container (min-width: 400px) {
.component {
width: 50%;
}
}
@container (min-width: 600px) {
.component {
width: 33.333%;
}
}
/* Block container */
.card-container {
container-type: block-size;
}
/* Inline container */
.sidebar {
container-type: inline-size;
}
/* Both dimensions */
.responsive-grid {
container-type: size;
}
@container (min-width: 300px) {
.card {
flex-direction: row;
}
}
@container (max-width: 299px) {
.card {
flex-direction: column;
}
}
@container (min-width: 400px) and (max-height: 600px) {
.content {
display: grid;
grid-template-columns: 1fr 1fr;
}
}
Container queries introduce new units that are relative to the container:
.responsive-text {
font-size: clamp(1rem, 5cqi, 2rem); /* Container inline size */
line-height: 1.2;
}
.responsive-spacing {
padding: 10cqb; /* Container block size */
margin: 5cqi; /* Container inline size */
}
/* Shorthand for common patterns */
@container (inline-size > 400px) {
.card {
--layout: horizontal;
}
}
@container (block-size > 300px) {
.sidebar {
--expanded: true;
}
}
.card {
container-type: inline-size;
display: flex;
flex-direction: column;
gap: 1rem;
}
.card-image {
aspect-ratio: 16/9;
}
.card-content {
flex: 1;
}
/* Responsive card layout */
@container (min-width: 300px) {
.card {
flex-direction: row;
}
.card-image {
flex: 0 0 200px;
}
}
.widget {
container-type: size;
background: white;
border-radius: 8px;
padding: 1rem;
}
.widget-header {
display: flex;
align-items: center;
gap: 0.5rem;
}
.widget-content {
margin-top: 1rem;
}
/* Responsive widget behavior */
@container (max-width: 250px) {
.widget-header {
flex-direction: column;
text-align: center;
}
}
@container (min-height: 400px) {
.widget-content {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 1rem;
}
}
.nav {
container-type: inline-size;
display: flex;
align-items: center;
gap: 1rem;
}
.nav-item {
padding: 0.5rem 1rem;
border-radius: 4px;
}
/* Responsive navigation */
@container (max-width: 500px) {
.nav {
flex-wrap: wrap;
}
.nav-item {
padding: 0.25rem 0.5rem;
font-size: 0.875rem;
}
}
// Check for container query support
if (CSS.supports('container-type: inline-size')) {
document.body.classList.add('supports-container-queries');
} else {
document.body.classList.add('fallback-layout');
}
/* Base styles for all browsers */
.component {
display: flex;
flex-direction: column;
}
/* Enhanced layout for supporting browsers */
@supports (container-type: inline-size) {
.component-container {
container-type: inline-size;
}
@container (min-width: 400px) {
.component {
flex-direction: row;
}
}
}
Container queries are generally performant, but consider:
/* Efficient: Single container for multiple queries */
.parent {
container-type: inline-size;
}
@container (min-width: 300px) {
.child-one { /* styles */ }
.child-two { /* styles */ }
.child-three { /* styles */ }
}
/* Less efficient: Multiple containers */
.child-one { container-type: inline-size; }
.child-two { container-type: inline-size; }
.child-three { container-type: inline-size; }
/* Step 1: Add container query support alongside media queries */
.component {
/* Base styles */
}
/* Media query for viewport-level concerns */
@media (min-width: 768px) {
.layout {
/* Layout changes */
}
}
/* Container query for component-level concerns */
@supports (container-type: inline-size) {
.component-container {
container-type: inline-size;
}
@container (min-width: 300px) {
.component {
/* Component-specific changes */
}
}
}
/* Before: Media query approach */
.news-grid {
display: grid;
grid-template-columns: 1fr;
gap: 1rem;
}
.news-item {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
@media (min-width: 768px) {
.news-grid {
grid-template-columns: 1fr 1fr;
}
.news-item {
flex-direction: row;
}
}
/* After: Container query approach */
.news-grid {
display: grid;
grid-template-columns: 1fr;
gap: 1rem;
}
.news-item {
container-type: inline-size;
display: flex;
flex-direction: column;
gap: 0.5rem;
}
@container (min-width: 400px) {
.news-item {
flex-direction: row;
}
}
/* Container query utilities */
.container-sm { container-type: inline-size; }
.container-md { container-type: inline-size; }
.container-lg { container-type: inline-size; }
/* Responsive utilities */
@container (min-width: 300px) { .cq:sm:flex-row { flex-direction: row !important; } }
@container (min-width: 500px) { .cq:md:flex-row { flex-direction: row !important; } }
@container (min-width: 700px) { .cq:lg:flex-row { flex-direction: row !important; } }
/* Visual debugging */
.container {
container-type: inline-size;
outline: 2px dashed red;
outline-offset: -2px;
}
@container (min-width: 400px) {
.container {
outline-color: green;
}
}
Current implementation includes:
The CSS working group is exploring:
Use container queries for:
Use media queries for:
/* Optimize container query performance */
.efficient-container {
container-type: inline-size;
contain: layout style;
}
/* Batch related queries */
@container (min-width: 300px) {
.component-a { /* styles */ }
.component-b { /* styles */ }
.component-c { /* styles */ }
}
Container queries represent a paradigm shift in responsive design, moving from viewport-centric to component-centric responsive design. They enable:
As browser support continues to grow and the feature matures, container queries will become an essential tool in every frontend developer’s toolkit. The future of responsive design is here, and it’s more flexible, maintainable, and powerful than ever before.
Start experimenting with container queries in your projects today, and discover how they can simplify your responsive design workflow while creating more adaptable user interfaces.
Have you started using container queries in your projects? What challenges or successes have you encountered? Feel free to reach out - I’d love to discuss your experiences with modern CSS responsive design!