Container queries revolutionise how we build responsive components...
"Container queries are the most requested CSS feature for over a decade!"
They finally allow us to create truly reusable components.
Finally! Components that respond to their container's size, not the viewport. Build truly reusable components that work anywhere.
Container queries allow you to apply styles based on the size of a containing element rather than the viewport. This means your components can adapt to any layout context - sidebar, main content, or anywhere else!
/* Responds to viewport only */
@media (min-width: 768px) {
.card {
display: grid;
grid-template-columns: 200px 1fr;
}
}
/* Problem: Card looks wrong in sidebar! */
/* Responds to container size */
.card-container {
container-type: inline-size;
}
@container (min-width: 400px) {
.card {
display: grid;
grid-template-columns: 200px 1fr;
}
}
Resize the containers below to see how the same component adapts to different sizes
Learn everything from basics to advanced techniques including Container Queries, :has(), and more!
Learn everything from basics to advanced techniques including Container Queries, :has(), and more!
/* Define container */
.product-card-container {
container-type: inline-size;
container-name: card;
}
/* Default mobile-first styles */
.product-card-cq {
display: flex;
flex-direction: column;
background: white;
border-radius: 1rem;
overflow: hidden;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
/* Compact layout for small containers */
@container card (max-width: 399px) {
.product-image {
height: 120px;
}
.product-description {
display: none;
}
.product-meta {
flex-direction: column;
gap: 0.5rem;
}
}
/* Horizontal layout for medium containers */
@container card (min-width: 400px) {
.product-card-cq {
flex-direction: row;
}
.product-image {
width: 200px;
height: 150px;
}
.product-button {
padding: 0.75rem 1.5rem;
}
}
/* Enhanced layout for large containers */
@container card (min-width: 600px) {
.product-content {
padding: 2rem;
}
.product-title {
font-size: 1.5rem;
}
.product-meta {
justify-content: space-between;
}
}
This text scales with container width!
/* Container query units */
.units-container {
container-type: size;
}
.cqw-text {
/* 5% of container width */
font-size: clamp(1rem, 5cqw, 2rem);
}
.cqh-box {
/* 30% of container height */
height: 30cqh;
display: grid;
place-items: center;
background: var(--gradient-primary);
color: white;
border-radius: 0.5rem;
}
/* Other units:
cqi - inline size
cqb - block size
cqmin - smaller of cqi/cqb
cqmax - larger of cqi/cqb */
/* Named containers for specificity */
.outer-container {
container-type: inline-size;
container-name: outer;
padding: 2rem;
background: #f3f4f6;
}
.inner-container {
container-type: inline-size;
container-name: inner;
padding: 1rem;
background: white;
}
/* Target specific container */
@container inner (min-width: 300px) {
.responsive-box {
background: var(--colour-primary);
color: white;
padding: 1rem;
}
}
/* Can also combine names */
@container outer (min-width: 500px) and
inner (min-width: 300px) {
.responsive-box {
font-size: 1.25rem;
}
}
Components adapt to container styles!
Same component, different container style
/* Style queries (experimental) */
.theme-container {
container-type: inline-size;
}
/* Query custom properties */
@container style(--theme: dark) {
.theme-card {
background: #1a1a1a;
color: white;
border-color: #333;
}
}
@container style(--theme: light) {
.theme-card {
background: white;
color: #333;
border-color: #e5e7eb;
}
}
/* Combine size and style queries */
@container (min-width: 400px) and
style(--theme: dark) {
.theme-card {
padding: 2rem;
border-width: 2px;
}
}
Container queries revolutionise how we build responsive components...
"Container queries are the most requested CSS feature for over a decade!"
They finally allow us to create truly reusable components.
/* Article container setup */
.article-container {
container-type: inline-size;
container-name: article;
}
/* Base styles */
.article-cq {
background: var(--colour-background);
border-radius: var(--radius-lg);
padding: 1.5rem;
}
/* Narrow containers (sidebar) */
@container article (max-width: 400px) {
.article-header {
text-align: center;
}
.article-title {
font-size: 1.25rem;
}
.article-meta {
display: none;
}
blockquote {
margin: 1rem 0;
padding-left: 1rem;
font-size: 0.9rem;
}
}
/* Wide containers (main content) */
@container article (min-width: 600px) {
.article-cq {
padding: 3rem;
}
.article-title {
font-size: 2.5rem;
margin-bottom: 1rem;
}
.article-content {
font-size: 1.125rem;
line-height: 1.7;
}
blockquote {
margin: 2rem -1rem;
padding: 1.5rem 2rem;
background: var(--colour-surface);
border-left: 4px solid var(--colour-primary);
font-size: 1.25rem;
}
}
Use `inline-size` for horizontal queries, `size` for both dimensions. Most components only need `inline-size`.
Container queries have minimal performance impact. The browser optimises them efficiently.
Always provide sensible defaults. Container queries should enhance, not break, your layout.
Think of containers like Russian dolls - each knows its own size perfectly. Brilliant!