Overview
Container Queries are a CSS feature that allows you to apply styles based on the size of an element’s container rather than the viewport. Unlike traditional media queries that depend on the entire viewport size, container queries enable styles to change based on the parent element’s size, making it possible to create more modular and reusable components.
Why Use Container Queries
More Flexible Component Design
Traditional media queries could only reference the size of the entire viewport. However, container queries allow you to determine styles based on the actual container size where the component is placed.
This enables layout decisions based on the space that components actually occupy rather than viewport size, allowing for more precise and intuitive design control.
Distinguishing from Media Queries
Container queries don’t completely replace media queries. The recommended approach is to use them as follows:
- Media Queries: For overall page layout and
position: fixed
elements - Container Queries: For internal layout of individual components
This distinction allows you to build a more maintainable CSS architecture.
/* Traditional media query (viewport-based) */
@media (max-width: 768px) {
.cards {
flex-direction: column;
}
}
/* Container query (parent element-based) */
@container (max-width: 300px) {
.cards {
flex-direction: column;
}
}
Basic Usage
1. Defining Containers
First, define the parent element of the element you want to use container queries with as a “query container.”
.container {
container-type: inline-size; /* Enable width-based queries */
}
/* or */
.container {
container-type: size; /* Enable queries based on both width and height */
}
container-type
values:
inline-size
: Monitor width only (most common)size
: Monitor both width and heightnormal
: Disable container queries (default)
2. Writing Container Queries
Apply styles based on the size of the defined container.
.cards {
display: flex;
gap: 1rem;
}
@container (max-width: 400px) {
.cards {
flex-direction: column;
}
.cards__image {
width: 100%;
}
}
@container (min-width: 600px) {
.cards {
padding: 2rem;
}
.cards__title {
font-size: 2rem;
}
}
3. Named Containers
When using multiple containers, you can distinguish them by giving them names. This allows you to clearly specify which container the query refers to.
.sidebar {
container-type: inline-size;
container-name: sidebar;
}
.main-content {
container-type: inline-size;
container-name: main;
}
/* Queries for specific containers */
@container sidebar (max-width: 250px) {
.widget {
/* Styles when sidebar is narrow */
font-size: 0.875rem;
padding: 0.5rem;
}
}
@container main (min-width: 800px) {
.article {
/* Styles when main content is wide */
columns: 2;
column-gap: 2rem;
}
}
Shorthand notation:
.container {
container: sidebar / inline-size; /* name / type */
}
Practical Example: Responsive Card Component
The following is an example of a card component whose layout changes according to container size.
/* Card container definition */
.card-container {
container-type: inline-size;
container-name: card;
}
.card {
display: grid;
gap: 1rem;
padding: 1rem;
border: 1px solid #e0e0e0;
border-radius: 8px;
background: white;
}
/* Narrow container: vertical layout */
@container card (max-width: 350px) {
.card {
grid-template-columns: 1fr;
text-align: center;
}
.card__image {
width: 100%;
max-width: 200px;
margin: 0 auto;
}
.card__title {
font-size: 1.25rem;
}
}
/* Medium container: image and content side by side */
@container card (min-width: 351px) and (max-width: 599px) {
.card {
grid-template-columns: 120px 1fr;
align-items: start;
}
.card__title {
font-size: 1.125rem;
}
}
/* Wide container: spacious layout */
@container card (min-width: 600px) {
.card {
grid-template-columns: 200px 1fr;
align-items: center;
padding: 2rem;
}
.card__content {
padding-left: 1.5rem;
}
.card__title {
font-size: 1.5rem;
margin-bottom: 0.75rem;
}
}
This way, the same card component will always have the optimal layout applied, even when placed in containers of different sizes.
Browser Support
Support Status
Container queries are a relatively new feature, but they are widely supported by major modern browsers:
- Chrome: 105+ (August 2022~)
- Firefox: 110+ (February 2023~)
- Safari: 16.0+ (September 2022~)
- Edge: 105+ (September 2022~)
Fallback Strategy
If you need to support older browsers, consider the following approaches:
/* Fallback styles */
.card {
display: block;
}
/* For container query-compatible browsers */
@supports (container-type: inline-size) {
.card-container {
container-type: inline-size;
}
@container (min-width: 400px) {
.card {
display: grid;
grid-template-columns: 200px 1fr;
}
}
}
Detailed support status: Can I use: CSS Container Queries