CSS Container Queries
Create truly responsive components that adapt based on their container size, not just the viewport!
What Are CSS Container Queries?
CSS Container Queries allow you to apply styles to elements based on the size of their containing element, rather than the size of the viewport (as with media queries). This enables truly modular, component-based responsive design.
Container queries use the @container rule to conditionally apply CSS when a specific container condition is true.
- Component-Based Design: Style elements based on their parent container's size
- Reusable Components: Create components that adapt to any context they're placed in
- Modular Layouts: Build layouts that respond to their available space
- Reduced Complexity: Simplify responsive design by focusing on components, not just viewport
Example 1: Basic Container Query Syntax
/* Define a containment context */
.container {
container-type: inline-size;
width: 100%;
resize: horizontal;
overflow: auto;
border: 1px dashed #ccc;
}
/* Default card styles */
.card {
padding: 1rem;
background-color: #f0f4ff;
border-radius: 8px;
}
/* Apply when container width is 400px or less */
@container (max-width: 400px) {
.card {
background-color: #e74c3c;
color: white;
padding: 0.5rem;
}
}
Resize the container (drag the bottom-right corner) to see the card change styles when the container width is 400px or less.
Container Query Components
- container-type: Establishes a containment context (values:
size,inline-size,normal) - container-name: Optional name for the container to target it specifically
- @container: The at-rule that begins a container query
- Container Features: Conditions about the container dimensions (e.g.,
width,height,aspect-ratio) - Logical Operators:
and,not,orto combine conditions
Basic syntax: @container [container-name] ([container-feature]) { /* CSS rules */ }
Example 2: Named Containers
/* Define named containment contexts */
.sidebar {
container-type: inline-size;
container-name: sidebar;
width: 100%;
resize: horizontal;
overflow: auto;
border: 1px dashed #3498db;
padding: 1rem;
margin-bottom: 1rem;
}
.main-content {
container-type: inline-size;
container-name: main;
width: 100%;
resize: horizontal;
overflow: auto;
border: 1px dashed #9b59b6;
padding: 1rem;
}
/* Target specific containers */
@container sidebar (max-width: 300px) {
.widget {
background-color: #3498db;
color: white;
}
}
@container main (min-width: 400px) {
.widget {
background-color: #9b59b6;
color: white;
}
}
Resize both containers to see how the same widget component adapts differently based on which container it's in.
Container Query Units
CSS Container Queries introduce new relative length units that are based on the dimensions of the query container:
- cqw: 1% of a query container's width
- cqh: 1% of a query container's height
- cqi: 1% of a query container's inline size
- cqb: 1% of a query container's block size
- cqmin: The smaller value of cqi or cqb
- cqmax: The larger value of cqi or cqb
These units allow for fluid typography and spacing that scales with the container size.
Example 3: Container Query Units
/* Define a containment context */
.cq-units-demo {
container-type: inline-size;
width: 100%;
resize: horizontal;
overflow: auto;
border: 1px dashed #ccc;
padding: 1rem;
}
/* Use container query units for fluid sizing */
.cq-heading {
font-size: calc(1rem + 2cqi);
margin-bottom: 0.5cqi;
}
.cq-text {
font-size: calc(0.8rem + 0.5cqi);
}
Fluid Typography
This text scales fluidly based on the container's inline size using container query units (cqi).
Resize the container to see how the text size adjusts proportionally to the container width.
Container Queries vs. Media Queries
Container Queries
Style elements based on their parent container's size, enabling truly modular components.
/* Define container */
.card-container {
container-type: inline-size;
}
/* Base styles */
.card { display: block; }
/* Container-based styles */
@container (min-width: 400px) {
.card { display: flex; }
}
Media Queries
Style elements based on the viewport size, affecting all matching elements on the page.
/* Base styles */
.card { display: block; }
/* Viewport-based styles */
@media (min-width: 768px) {
.card { display: flex; }
}
Example 4: Responsive Layout Component
.product-container {
container-type: inline-size;
width: 100%;
resize: horizontal;
overflow: auto;
border: 1px dashed #ccc;
}
.product-card {
display: grid;
grid-template-columns: 1fr;
gap: 1rem;
padding: 1rem;
background-color: #fff;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.product-image {
background-color: #f0f4ff;
aspect-ratio: 16/9;
border-radius: 4px;
}
.product-info {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
@container (min-width: 500px) {
.product-card {
grid-template-columns: 200px 1fr;
}
}
Product Title
Product description goes here. This is a responsive product card that changes layout based on its container width.
Resize the container to see how the product card layout changes from stacked to side-by-side when the container is at least 500px wide.
Best Practices & Tips
- Component-First Thinking: Design components to be self-contained and adaptable to any context.
- Combine with Media Queries: Use container queries for component-level responsiveness and media queries for page-level layout changes.
- Use Logical Properties: Prefer
inline-sizeoverwidthfor better internationalization support. - Performance Considerations: Be mindful of nesting container queries, as they can impact performance.
- Progressive Enhancement: Provide fallbacks for browsers that don't support container queries.
- Container Query Units: Leverage
cqi,cqw, etc. for fluid typography and spacing within containers.