CSS Container Queries
What are CSS Container Queries?
CSS Container Queries allow you to style elements based on the size of their containing element rather than the viewport size. This enables truly modular, responsive components that can adapt to their context regardless of where they're placed on the page.
Unlike media queries that respond to viewport dimensions, container queries respond to the dimensions of a specific container element, making components more modular and reusable.
Browser Support
Container queries are well-supported in modern browsers:
- Chrome 105+
- Firefox 110+
- Safari 16+
- Edge 105+
Basic Syntax
To use container queries, you need to:
- Establish a containment context
- Write container queries that respond to that context
Step 1: Define Container Context
.container {
container-type: inline-size;
/* or use the shorthand */
container: inline-size;
}
Step 2: Write Container Queries
@container (min-width: 400px) {
.card {
display: flex;
gap: 1rem;
}
}
Container Types
The container-type
property accepts several values:
inline-size
Creates containment in the inline direction (width in horizontal writing modes):
.sidebar {
container-type: inline-size;
}
@container (min-width: 300px) {
.widget {
padding: 2rem;
}
}
size
Creates containment in both dimensions:
.card-container {
container-type: size;
}
@container (min-width: 400px) and (min-height: 300px) {
.card {
aspect-ratio: 16/9;
}
}
block-size
Creates containment in the block direction:
.content-area {
container-type: block-size;
}
@container (min-height: 500px) {
.article {
columns: 2;
}
}
Named Containers
You can name containers for more specific targeting:
.main-content {
container-name: main;
container-type: inline-size;
}
.sidebar {
container-name: sidebar;
container-type: inline-size;
}
/* Target specific container */
@container main (min-width: 800px) {
.article {
columns: 3;
}
}
@container sidebar (min-width: 250px) {
.widget {
flex-direction: row;
}
}
Container Query Units
Container queries introduce new length units:
cqw
- 1% of container's widthcqh
- 1% of container's heightcqi
- 1% of container's inline sizecqb
- 1% of container's block sizecqmin
- Smaller value betweencqi
orcqb
cqmax
- Larger value betweencqi
orcqb
.container {
container-type: size;
}
.responsive-text {
font-size: clamp(1rem, 4cqi, 2rem);
padding: 2cqi;
}
.square {
width: 50cqmin;
height: 50cqmin;
}
Practical Examples
Responsive Card Component
.card-container {
container-type: inline-size;
padding: 1rem;
}
.card {
background: white;
border-radius: 8px;
padding: 1rem;
}
/* Small container - stack content */
.card {
display: block;
}
.card img {
width: 100%;
margin-bottom: 1rem;
}
/* Medium container - side by side */
@container (min-width: 400px) {
.card {
display: flex;
gap: 1rem;
}
.card img {
width: 150px;
margin-bottom: 0;
}
}
/* Large container - more spacing */
@container (min-width: 600px) {
.card {
padding: 2rem;
gap: 2rem;
}
.card img {
width: 200px;
}
}
Navigation Component
.nav-container {
container-type: inline-size;
}
.nav {
display: flex;
flex-wrap: wrap;
gap: 1rem;
}
/* Default - stacked menu */
.nav-menu {
flex-direction: column;
width: 100%;
}
/* Wide container - horizontal menu */
@container (min-width: 600px) {
.nav-menu {
flex-direction: row;
width: auto;
}
}
Best Practices
1. Start with Container Context
Always establish the containment context before writing container queries:
/* ✓ Good */
.component-wrapper {
container-type: inline-size;
}
@container (min-width: 400px) {
.component { /* styles */ }
}
/* ✗ Bad - no containment context */
@container (min-width: 400px) {
.component { /* styles */ }
}
2. Use Meaningful Container Names
/* ✓ Good */
.product-grid {
container: products / inline-size;
}
@container products (min-width: 600px) {
.product-card {
width: calc(50% - 1rem);
}
}
/* ✗ Less clear */
.wrapper {
container: c1 / inline-size;
}
3. Consider Performance
Container queries can be expensive. Use them judiciously:
/* ✓ Good - specific targeting */
.card-container {
container-type: inline-size;
}
/* ✗ Avoid - too broad */
* {
container-type: inline-size;
}
4. Progressive Enhancement
Provide fallbacks for older browsers:
/* Base styles for all browsers */
.card {
display: block;
padding: 1rem;
}
/* Enhanced layout with container queries */
@supports (container-type: inline-size) {
.card-container {
container-type: inline-size;
}
@container (min-width: 400px) {
.card {
display: flex;
gap: 1rem;
}
}
}
Debugging Tips
- Use browser dev tools to inspect container contexts
- Add visual indicators for containers during development:
[style*="container"] {
outline: 2px dashed blue;
}
[style*="container"]::before {
content: "Container";
background: blue;
color: white;
padding: 2px 4px;
}
Common Use Cases
- Component-based layouts: Cards, widgets, sidebars
- Responsive typography: Text that adapts to container size
- Flexible grids: Grid layouts that respond to container width
- Navigation patterns: Menus that adapt to available space
- Media containers: Images and videos that fit their container
Container queries represent a major evolution in responsive design, enabling truly modular and reusable components that can adapt to any context.