Intrinsic Layout Fallbacks: Baselines That Adapt Without Any Query
The usual fallback for container queries is a viewport media query: "if the browser cannot measure the container, measure the window instead". That is a reasonable approximation for components that always span the page and a poor one for components that appear in sidebars, cards, modals and grid cells, where the window says nothing about the space available. There is a better baseline for most components: an intrinsic layout that adapts to its real available space using features every browser has supported for years. This page shows the four intrinsic building blocks, how to combine them into a component baseline, and how to layer container queries on top as an enhancement. It belongs to Container Query Fallbacks in the Mastering Container Queries & Responsive Layouts guide.
Why intrinsic beats viewport as a fallback
A viewport fallback answers the wrong question. A card with @media (min-width: 48rem) { … side-by-side … } switches to a side-by-side layout when the window is wide — including when the card sits in a narrow sidebar of that wide window, where side-by-side squeezes its text to a few words per line. The fallback is right only for the placements the designer happened to imagine.
Intrinsic techniques measure the right thing without asking. flex-wrap decides whether items fit on one line from the real width of their container. Grid's auto-fit with minmax() decides how many columns fit. min(), max() and clamp() bound sizes against percentages of the real container. These decisions happen during layout, in every placement, in every browser from the last several years — so an intrinsic baseline is correct in the sidebar and the full-width band.
The four intrinsic building blocks
flex-wrapwith aflex-basis. Items share a row while their preferred sizes fit and wrap when they do not. Best for rows of unequal items and two-part components such as media objects.- Grid
repeat(auto-fit, minmax(min, 1fr)). As many equal columns as fit, each at leastmin. Best for collections of similar items. min()/max()/clamp()with percentages. Sizes that track the container but stay within bounds, such aswidth: min(100%, 40rem)orpadding: clamp(0.75rem, 4%, 2rem).- Intrinsic sizing keywords.
fit-content,min-contentandmax-contentsize elements from their content, for labels, buttons and sidebars that should be exactly as wide as they need.
The full explanations live in Breakpoint-Free Rows With flex-wrap, auto-fit and minmax() Grids and Layout Widths With min(), max() and clamp(). Here they are combined into a component baseline.
The complete implementation
The product card below is fully responsive in every browser through intrinsic techniques alone. A container query then adds two refinements that intrinsic layout cannot express — a larger title and a square image in wide containers.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Intrinsic baseline plus container enhancement</title>
<style>
body { font: 15px/1.5 system-ui, sans-serif; margin: 1rem; }
/* ---------- Baseline: no queries at all ---------- */
.product {
display: flex;
flex-wrap: wrap; /* stack when the pair no longer fits */
gap: 1rem;
padding: clamp(0.75rem, 4%, 1.5rem); /* spacing tracks the card's width */
border: 1px solid #cbd5e1;
border-radius: 12px;
}
.product__media {
flex: 1 1 10rem; /* prefer 10rem beside the text */
aspect-ratio: 4 / 3;
border-radius: 8px;
background: linear-gradient(135deg, #fde68a, #f59e0b);
}
.product__body {
flex: 999 1 16rem; /* grow first; wrap below 16rem */
min-width: 0;
}
.product__title { margin: 0 0 0.25rem; font-size: 1.1rem; }
.product__actions {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
}
.product__actions > * { flex: 1 1 8rem; } /* buttons share a row or stack */
/* ---------- Enhancement: container queries ---------- */
.product-slot { container-type: inline-size; }
@container (width > 36rem) {
.product__title { font-size: 1.35rem; }
.product__media { aspect-ratio: 1; flex-grow: 0; }
}
</style>
</head>
<body>
<div class="product-slot">
<article class="product">
<div class="product__media" role="img" aria-label="Amber ceramic mug"></div>
<div class="product__body">
<h3 class="product__title">Amber ceramic mug</h3>
<p>Hand-thrown, 350 ml, dishwasher safe.</p>
<div class="product__actions">
<button type="button">Add to basket</button>
<button type="button">Save</button>
</div>
</div>
</article>
</div>
</body>
</html>
The large flex-grow on the body — 999 — is a small trick worth knowing: when the media and the body share a row, almost all spare space goes to the text, so the image stays near its preferred 10rem. When the row wraps, each item is alone on its line and grows to fill it regardless. The container query is purely additive: remove it and the card is still correct everywhere, just less polished at wide sizes.
The key technique: baseline first, enhancement second
The structure that makes this robust is ordering. Everything the component needs to be usable is written outside any query and relies only on long-supported features. Everything that makes it better at particular sizes sits inside @container rules, which unsupported engines ignore.
A useful discipline in code review is to ask of every container query rule: "if this rule vanished, would the component break or just look plainer?" Rules whose absence breaks the component belong in the baseline, rewritten intrinsically if possible. Only rules whose absence makes the component plainer belong behind the query.
Converting an existing query-driven component
Many components were written query-first: a stacked default and one or two @container rules that rearrange everything. Converting them to an intrinsic baseline is a matter of asking, for each rule inside a query, whether an intrinsic technique can produce the same arrangement from the available space.
Layout switches between a stack and a row almost always can: replace flex-direction: column in the default and flex-direction: row in the query with a single wrapping row whose items have sensible flex-basis values. Column-count changes in a grid almost always can: replace fixed grid-template-columns per band with one repeat(auto-fit, minmax(…)) definition. Padding and gap steps usually can: replace per-band values with one clamp() expression that grows with a percentage of the container.
What remains in the queries after that pass is the genuinely conditional design — the typography step, the hidden secondary line, the changed aspect ratio. The component typically ends up with far fewer query rules, each of them smaller, and a baseline that behaves well at every width rather than only at the widths the designer tested. Converting the thresholds of the remaining rules to exclusive range syntax, as described in Container Query Range Syntax and Logic, finishes the tidy-up.
What intrinsic techniques cannot do
Intrinsic layout decides whether things fit. It cannot make design decisions that are not about fit:
- Typography changes at a threshold. A title that should jump from 1.1rem to 1.35rem at a card width is a design choice; fluid type with
clamp()gives continuous scaling but not a step. - Hiding or revealing secondary content. Nothing intrinsic hides the author name on a very narrow card.
- Changing aspect ratios or orientation. An image that should be 4:3 when stacked and square when beside text needs a condition.
- Different component variants. Switching from a list to a table layout is a structural change that needs a query.
These are precisely the enhancements a container query should provide. When a design leans heavily on them and the fallback matters, a viewport media query inside @supports not (container-type: inline-size) can approximate them for the placements that matter most — the approach described in Handling Container Query Fallbacks for Older Browsers.
Motion in the baseline
The same principle extends to animation. A component that animates when it changes layout — cards reflowing into a new arrangement, say — should be fully usable with no animation at all, with motion added as an enhancement gated by support and preference. Layout changes produced by intrinsic wrapping happen continuously as the container resizes and cannot be meaningfully animated anyway; threshold changes from container queries can be, as shown in Container-Query-Triggered Keyframe Animations.
Browser support
The intrinsic building blocks are long established: CSS Grid with repeat() and minmax() from Chrome 57, Firefox 52 (repeat() 76) and Safari 10.1; min(), max() and clamp() from Chrome and Edge 79, Firefox 75 and Safari 13.1; aspect-ratio from Chrome and Edge 88, Firefox 89 and Safari 15; and flex gap in all current engines. Container queries, the enhancement layer, are supported in Chrome and Edge 105+, Firefox 110+ and Safari 16+.
FAQ
What is an intrinsic layout?
A layout whose arrangement is decided by the browser from the available space and the content's own sizes, using features such as flex-wrap, grid auto-fit with minmax(), and clamp() or min() for sizes. It adapts continuously without any query or breakpoint.
Why use an intrinsic layout as a fallback rather than a media query? A media query responds to the viewport, which is the wrong measurement for a component placed in a sidebar or grid cell. An intrinsic layout responds to the component's real available space, just as a container query would, so it is correct in more placements.
Do I still need container queries if intrinsic layouts work? Often, yes, but for less. Intrinsic techniques handle whether things fit. Container queries handle design changes that are not about fit, such as switching typography, hiding secondary content, or changing an image's aspect ratio at a threshold.
How do I layer container queries on top of an intrinsic baseline?
Write the intrinsic layout outside any query so every browser gets it. Then add @container rules that refine it, optionally inside @supports (container-type: inline-size). Browsers without container queries keep the baseline; others get the refinement.
Related
- Container Query Fallbacks — the parent guide.
- Container Query Polyfill: Is It Worth It? — the script-based alternative.
- Flexbox Layout Patterns — the flex techniques used in the baseline.
- Motion That Scales With Container Size — enhancement applied to motion.
Related articles
More pages in the same section.