Understanding height, containment and side effects correctly
container-type: size extends container queries into the block direction, but it enforces genuine size containment with noticeable side effects: without an explicit height, the container collapses to zero. Understanding when size is the right choice instead of inline-size avoids the most common layout bugs with this feature.
Table of Contents
- 1. Why container-type size is more than inline-size
- 2. The three values of container-type at a glance
- 3. Explicit containment and its side effects
- 4. Defining fixed heights so the container does not collapse
- 5. Block size queries: when they are actually needed
- 6. Combining container-type size with aspect-ratio
- 7. Using style queries and container-type size together
- 8. Performance aspects: containment costs and recalculation
- 9. container-type size compared to inline-size and normal
- 10. Summary
- 11. FAQ
1. Why container-type size is more than inline-size
Most introductions to container queries limit themselves to container-type: inline-size, because this value is entirely sufficient for the most common layout problems, responsive cards and components based on available width. container-type: size goes a decisive step further: it allows queries against both the width and the height of a container, meaning genuine two dimensional container queries. This opens up new use cases, for example components that need to adapt to the available vertical height in a sidebar panel or a dashboard widget.
The price for this additional capability is stricter containment: container-type: size enforces both size and layout containment on the element, which means the container is no longer allowed to derive its own size from its content. Without an explicit height, such a container collapses to a height of zero pixels, a behavior that surprises many developers the first time they use container-type: size and causes the notorious "empty container" bug.
2. The three values of container-type at a glance
The property container-type supports three values. normal is the default, the element does not become a container query container and behaves like any other element. inline-size activates containment only along the inline axis, which is width in horizontal writing modes, and allows queries against that single dimension. container-type: size activates containment along both axes, inline and block direction, and allows queries against width and height simultaneously.
A key detail that is often overlooked: all three values cannot be mixed arbitrarily, an element is either not a container at all, a pure width container, or a full size container. There is no intermediate step such as "height containment only, without width containment" through container-type alone, anyone who only wants to query height still has to use container-type: size and can then specifically query only min-height or similar height conditions in the corresponding @container rule.
/* inline-size: only width containment, height derives from content normally */
.card-container {
container-type: inline-size;
container-name: card;
}
/* size: containment on BOTH axes, height must now be explicit */
.widget-container {
container-type: size;
container-name: widget;
height: 240px; /* required, otherwise this container collapses to 0px height */
}
@container widget (min-height: 200px) {
.widget-title { font-size: 1.25rem; }
}
3. Explicit containment and its side effects
The CSS Containment specification, on which container queries are built, defines several containment types: size, layout, style and paint. container-type: size internally sets contain: size layout style, which allows the browser to fully isolate the element during rendering, so that changes inside the container cannot affect the layout outside of it. This isolation is the foundation that makes it possible for the browser to evaluate container queries efficiently at all, without risking endless feedback loops between content and query.
The side effect of contain: size is that the container's content is completely ignored when the browser calculates its size. A container-type: size container with a variable amount of text inside does not automatically grow with the text, the text instead gets clipped or overflows, depending on the overflow setting. This side effect is intentional, not a malfunction, it is the reason why container-type: size is only suitable for layout areas with a known or externally controlled size, not for areas whose height should depend on the content.
4. Defining fixed heights so the container does not collapse
The practical consequence of the previous section: every container-type: size container needs an explicit height source that exists independently of its content. That can be a fixed pixel or rem height, a height derived through aspect-ratio combined with a fixed width, or a height provided by a surrounding grid or flexbox layout via height: 100%. Without one of these sources, the container stays at zero pixels height, and any content becomes effectively invisible, because the container has no extent to render beyond.
A proven pattern in grid layouts: the parent grid cell is given an explicit height through grid-template-rows, and the child element with container-type: size receives height: 100% to adopt that height. This keeps the height logic in the grid system, while the container query logic is solely responsible for the internal adaptation of the content. This separation prevents container-type: size from accidentally becoming the sole source of layout height, which quickly leads to unpredictable behavior.
/* PROBLEM: no explicit height source, container collapses to 0px */
.broken-widget {
container-type: size;
/* height is derived from content, but content is ignored under size containment */
}
/* SOLUTION 1: explicit fixed height */
.widget-fixed {
container-type: size;
height: 320px;
}
/* SOLUTION 2: height inherited from a parent grid row */
.dashboard-grid {
display: grid;
grid-template-rows: 200px 300px; /* explicit row heights */
}
.dashboard-grid > .widget-in-grid {
container-type: size;
height: 100%; /* inherits the row's explicit height */
}
5. Block size queries: when they are actually needed
Block size queries, meaning queries against a container's height in horizontal writing modes, are needed less often than inline size queries, but indispensable in certain scenarios. A typical example is a video player overlay that needs to render its controls more compactly once the available vertical space falls below a certain threshold, regardless of width. A second example is sidebar widgets in dashboard applications, where users can freely resize panels vertically and the component needs to react to what level of detail can still be sensibly displayed.
The key difference from inline size queries: while available width is usually relatively stable and dictated by the parent responsive grid, available height is more dynamic and harder to predict in many layouts, for example with variable window height or user resizing. container-type: size block size queries should therefore be used conservatively, only where a clear, repeatable use case actually exists, not as a blanket replacement for inline size queries.
.video-controls-container {
container-type: size;
container-name: player;
height: 100%; /* inherited from the video player wrapper */
}
/* React to available vertical space, not just width */
@container player (max-height: 120px) {
.video-controls {
flex-direction: row;
gap: 0.25rem;
}
.video-controls .label-text {
display: none; /* icons only when vertical space is tight */
}
}
@container player (min-height: 200px) {
.video-controls {
flex-direction: column;
gap: 0.75rem;
}
}
6. Combining container-type size with aspect-ratio
One of the most elegant solutions to the height collapse problem is combining container-type: size with aspect-ratio. Instead of defining a fixed pixel height that can become inappropriate at responsive widths, you define a fixed width and an aspect ratio via aspect-ratio: 16 / 9, from which the browser automatically calculates the height, independent of the internal content. This calculated height exists independently of containment and therefore does not collapse.
This pattern is especially suited for media cards, video thumbnails and product image containers, where a consistent aspect ratio across different screen sizes is desired, while both width and height based container queries are needed at the same time for the internal arrangement of badges, headings and call to action buttons. container-type: size combined with aspect-ratio thus delivers predictable heights without manual breakpoint maintenance.
.media-card-container {
container-type: size;
container-name: mediacard;
width: 100%;
aspect-ratio: 16 / 9; /* height is derived from width, never from content */
}
/* Both width and height conditions become available */
@container mediacard (min-width: 400px) and (min-height: 220px) {
.media-card-overlay {
padding: 1.5rem;
font-size: 1.125rem;
}
}
@container mediacard (max-width: 399px) {
.media-card-overlay {
padding: 0.5rem;
font-size: 0.875rem;
}
}
7. Using style queries and container-type size together
Style queries, queried via @container style(--variant: compact), work independently of the chosen container-type value, but can be meaningfully combined with container-type: size when a component needs to respond both to its own size and to a mode set through a custom property. A dashboard widget could, for example, react to available height to hide content, while also reacting to a custom property based variant to switch between a chart and a table representation.
Combining both types of queries allows granular but maintainable component logic: size based adjustments stay in one group of @container rules, state based adjustments in another, while both reference the same container established through container-type: size. This separation of size and state logic prevents confusing, deeply nested conditions inside a single rule.
8. Performance aspects: containment costs and recalculation
The containment enforced by container-type: size is generally performance friendly, because it allows the browser to isolate layout calculations to the container instead of re evaluating the entire document tree on every change. This isolation significantly reduces the cost of reflows in large, complex layouts, especially when many independent containers exist on the page at once, for example in a dashboard with numerous widgets.
A performance risk arises when developers apply container-type: size generously across many nested levels without checking actual necessity. Every additional containment boundary creates its own formatting context, which is unproblematic in moderation but creates unnecessary overhead with excessive nesting. The recommendation is to use container-type: size deliberately for components with an actual need for height queries and to stick with inline-size for all other cases, which requires less containment overhead.
9. container-type size compared to inline-size and normal
Choosing the right container-type value depends on the actual use case, not on a blanket preference for the most powerful option.
| container-type | Queryable Axes | Height Requirement | Typical Use |
|---|---|---|---|
| normal | None | None | Not a container query container |
| inline-size | Width | None, height follows content | Responsive cards, form layouts |
| size | Width and height | Explicitly required, otherwise collapse | Video overlays, dashboard widgets, media cards |
In practice, inline-size covers the vast majority of all responsive components, because width is the dominant layout dimension in modern, vertically scrolling websites. container-type: size remains a specialized tool for cases where a container's height is genuinely variable and relevant to the internal representation, with the clear prerequisite that this height must be defined explicitly to avoid the collapse bug.
Mironsoft
Modern CSS architecture and component based layout
Size based components without layout bugs?
We implement container-type size cleanly, define robust height sources, and combine size and style queries into maintainable, reusable components.
Architecture Review
Reviewing your existing container query structure for collapse risks
Component Refactoring
Combining height queries, aspect-ratio and style queries production ready
Performance Check
Reviewing containment boundaries for actual need instead of overuse
10. Summary
container-type: size extends container queries into the block direction and allows querying width and height at the same time, but in exchange enforces size containment on both axes. Without an explicit height source, whether through fixed dimensions, aspect-ratio, or a predefined grid row, the container collapses to zero pixels height. Block size queries are needed less often than pure width queries, but indispensable in video overlays and dashboard widgets.
Combining with aspect-ratio delivers predictable heights without manual breakpoint maintenance, while style queries enable additional, state based logic independent of size. On the performance side, container-type: size remains a specialized tool that should be used deliberately where height queries provide real value, while the majority of responsive components continue to work fine with inline-size.
container-type: size Queries in Detail — The Essentials at a Glance
Base Principle
container-type: size allows width and height queries, but enforces containment on both axes.
Height Requirement
Without an explicit height, for example via fixed dimensions or aspect-ratio, the container collapses to 0px.
Use Cases
Video overlays, dashboard widgets and media cards with a genuine need for height.
Performance
Use only deliberately, for most components inline-size with lower containment overhead is sufficient.