Container Queries in CSS (@container)
Responsive design usually relies on media queries (@media), which adapt layouts based on the viewport size.
But sometimes, a component needs to adjust to its parent container, not the whole screen.
That’s where CSS Container Queries (@container) help. They let elements respond to their container’s size, making components modular, reusable, and flexible across different layouts.
Why Use Container Queries?
- Component-friendly: Ideal for frameworks like React, Vue, and Angular.
- Reusable layouts: Cards, widgets, and sidebars adapt anywhere.
- Local control: Styles respond to the parent, not the screen.
- Simpler CSS: Fewer breakpoints and overrides.
- Future-ready: A smarter approach than traditional media queries.
Media Queries vs Container Queries
- Media Queries → Media queries adapt layouts to the device.
- Container Queries → Container queries adapt components to their parent container.
How to Use Container Queries
1: Define a Container
To enable container queries, you must declare a parent element as a query container:
container-type
inline-size
→ tracks the width only.size
→ tracks both width and height.
container-name
- Useful if you want to target a specific container in your query.
.container {
container-type: inline-size; /* enables queries based on container width */
container-name: card; /* optional name for targeting */
}
2: Write a Container Query
- Works like
@media
, but applies to the container, not the viewport. - If you use named containers, you can target them specifically:
@container (min-width: 40rem) {
.component {
display: flex;
gap: 1rem;
}
}
@container card (max-width: 500px) {
.card {
flex-direction: column;
}
}
Example 1: Responsive Card Layout
The card stacks vertically in small containers and becomes a row layout in wider ones.
<div class="card-container">
<div class="card">
<img src="image.jpg" alt="Example">
<p>This is a responsive card using container queries.</p>
</div>
</div>
.card-container {
container-type: inline-size;
container-name: card;
max-width: 600px;
margin: auto;
}
.card {
display: flex;
flex-direction: row;
gap: 1rem;
padding: 1rem;
border: 1px solid #ccc;
background: #fff;
border-radius: 10px;
}
/* Switch to vertical when container is narrow */
@container card (max-width: 400px) {
.card {
flex-direction: column;
text-align: center;
}
}
Example 2: Adaptive Sidebar Layout
The sidebar automatically stacks under the content if the parent container is too narrow.
<div class="layout">
<aside class="sidebar">Sidebar</aside>
<main class="content">Main Content</main>
</div>
.layout {
display: flex;
container-type: inline-size;
gap: 1rem;
}
.sidebar {
flex: 1;
background: #ddd;
}
.content {
flex: 3;
background: #fff;
}
/* When container is narrow */
@container (max-width: 600px) {
.layout {
flex-direction: column;
}
}
Example 3: Grid of Cards (Each Card Adapts Independently)
Each card responds based on its own width, not the overall grid or viewport.
<div class="grid">
<div class="grid__item card">Card 1</div>
<div class="grid__item card">Card 2</div>
<div class="grid__item card">Card 3</div>
</div>
.grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
gap: 1rem;
padding: 1rem;
}
.grid__item {
container-type: inline-size; /* each grid item acts as its own container */
}
.card {
border: 1px solid #ccc;
padding: 1rem;
background: #fafafa;
}
/* Each card adapts individually */
@container (min-width: 28rem) {
.card {
display: flex;
justify-content: space-between;
}
}