CSS Container Queries
CSS Container Queries: The Game-Changer for Component-Driven UI
For years, Media Queries have been the cornerstone of responsive web design. We’ve relied on them to adapt our layouts to the overall viewport size. But the modern web is built on components—self-contained units that can be dropped into various contexts, like a narrow sidebar, a wide main column, or a flexible grid. The problem? A card component that looks great in a wide viewport might break when placed in a narrow container within that same viewport, forcing developers to resort to complex, often brittle, workarounds.
Enter CSS Container Queries (CQ), the most significant leap for responsive design in years. Container Queries finally give us the ability to style an element based on the dimensions of its parent container, not the global viewport.
What are Container Queries?
At its core, a Container Query is an alternative to a Media Query that operates at the component level.
Instead of the @media at-rule, you use the @container at-rule.
1. Defining a Container
To use a size query, you first need to declare an element as a query container using the container-type property.
1
2
3
4
5
/* Declares a containment context on this element */
.post-container {
container-type: inline-size; /* Query based on the container's width (inline axis) */
container-name: 'post-area'; /* Optional: provides a name for targeting */
}
inline-size: Queries based on the container’s inline axis (width in a left-to-right writing mode). This is the most common use case.size: Queries based on both inline and block dimensions (width and height).normal: The element is not a query container for size queries but can be one for style queries (future feature).
2. Querying the Container
Once defined, any descendant of the container can use the @container rule to apply styles based on the container’s size.
1
2
3
4
5
6
7
8
9
/* Style for a card component inside the container */
@container post-area (max-width: 400px) {
.card-image {
display: none; /* Hide the image if the container is narrow */
}
.card-content {
font-size: 0.8rem; /* Shrink the text */
}
}
This simple pattern ensures your .card-content adapts intelligently, regardless of the overall viewport size. Whether the viewport is large or small, the card only cares about the space available to it from its direct parent.
The Power in Micro-Frontends (MFEs)
Container Queries are especially impactful when building UIs using a Micro-Frontend architecture.
Micro-Frontends involve breaking a large application (the frontend monolith) into smaller, independent, and autonomously deployable applications or features, often owned by different teams. These independent pieces—the Micro-Frontends—are then stitched together by a shell application to form a cohesive user interface.
1. True Component Isolation and Reusability
In an MFE world, component teams own their UI end-to-end. Before CQs, a component team had to anticipate all possible global media query breakpoints the shell might use.
- Before CQs: A
ProfileCardMFE had to be styled for viewport sizes like 768px, 1024px, etc., even if it was meant to display in a small, fixed-width sidebar MFE. - With CQs: The
ProfileCardMFE can define its own internal breakpoints based on its container’s size (e.g., “If my container is less than 300px wide, switch to a vertical layout”). The component becomes truly self-contained and portable, requiring zero knowledge of the overall page layout or viewport.
This boosts team autonomy, which is a core MFE benefit, by allowing component teams to develop and deploy without coordinating global style dependencies.
2. Simplified Integration and Reduced Collisions
MFEs are often integrated side-by-side, which can lead to CSS namespace collisions or confusing layout overrides.
CQs mitigate this by localizing layout logic. The style logic is tied to the component’s immediate surroundings (its container), not a global state (the viewport). This inherent locality dramatically reduces the complexity of integrating multiple independent UIs and makes debugging layout issues far more straightforward.
3. The Micro-Layout / Macro-Layout Split
Container Queries facilitate a clean separation of concerns:
- Macro-Layout (Page Level): Handled by traditional Media Queries. Use these for overall structural changes based on the viewport, like switching the main content column and sidebar from a two-column to a single-column layout.
- Micro-Layout (Component Level): Handled by Container Queries. Use these for fine-tuning the component’s internal arrangement based on the space it was given by the macro-layout.
This dual-system approach is a powerful tool for designing robust, scalable component systems in any large, modular application, especially Micro-Frontends.
Container Queries are stable in all major browsers and are a must-have for any modern developer looking to simplify responsive design and build truly robust components.
The video titled “Container queries - Designing in the Browser” is relevant because it provides a visual explanation and demo of how container queries work, which is the central topic of this blog post. Container queries - Designing in the Browser