Container Queries
Overview
Media Queries have a fatal architectural flaw: they only know the width of the ENTIRE browser window. Imagine building a 'Product Card' component. If it's in the main content area, it has plenty of space. But if you drop that exact same card into a narrow 250px Sidebar, it completely breaks, even if the user is on a 4K Desktop monitor! Container Queries (@container) fix this. They allow a component to style itself based purely on the physical size of its parent container, completely ignoring the viewport. This is the ultimate form of Component-Driven Design.
Syntax
/* 1. Define the Container */
.sidebar {
/* You MUST explicitly tell the browser this is a container! */
container-type: inline-size;
/* Optional: Give it a name for complex nesting */
container-name: sidebar-zone;
}
/* 2. Style the Component based on the Container's size! */
.product-card {
display: flex;
flex-direction: row;
}
/* If the .sidebar ever shrinks below 400px... */
@container sidebar-zone (max-width: 400px) {
.product-card {
/* Stack the card vertically, because it's being squished! */
flex-direction: column;
font-size: 0.8rem;
}
}Common Pitfalls
- Forgetting to declare
container-type: inline-size;on the parent. If you do not explicitly register the parent as a container, the browser will completely ignore any@containerqueries inside it. - Setting
container-typeglobally on the<body>. Container queries require the browser to perform complex ResizeObserver loops natively. Applying them universally to massive DOM elements will absolutely decimate your rendering performance.
Interview Questions
container-type: size; to query BOTH width and height easily?Because of infinite loops! If the container queries its own height, and then changes its child's font size... that font size changes the height of the container! The browser will infinitely loop and crash. inline-size (Width only) is the safe, standard way to use Container Queries.
Real-World Example
Building a perfectly modular Profile Component that looks great in a massive hero section AND in a tiny navbar dropdown, using the exact same HTML.
.profile-wrapper { container-type: inline-size; }
.profile-avatar { width: 100px; height: 100px; }
/* If the wrapper is squished into a tiny navbar... */
@container (width < 300px) {
.profile-avatar {
width: 40px; /* Shrink the avatar drastically! */
height: 40px;
}
.profile-bio { display: none; } /* Hide the text entirely */
}Check Your Knowledge
Test your understanding of Container Queries with these quick questions.