Concepts — Layout: Flex, Grid, Intrinsic Sizing & Container Queries
Phase 1 · Platform substrate · Specification area §4 (flexbox, grid, subgrid, container queries, media queries, intrinsic sizing, min/max-content, stacking contexts, positioning). Depends on fe-05.
1. What is it
Layout is the pipeline stage that turns styled boxes into geometry. This module covers the algorithms you choose between (block, flex, grid, absolute), the sizing vocabulary that decides how much measuring the browser must do, and container queries — the first mechanism that lets a component respond to its own context rather than the viewport.
2. Why it matters
Layout-mode folklore is wrong, and expensive. Measured: block, inline-block, float, flex, grid and absolute positioning across 20,000 items span 1.4× — and absolute positioning, the mode usually described as fastest, was the slowest (75.5 ms vs block's 55.1 ms). On relayout, flex was the fastest (7.3 ms). Teams contort component APIs to avoid flex/grid on performance grounds that do not survive measurement.
Where layout cost actually lives is how much you ask the browser to lay out. Compare this
module's 1.4× spread against fe-05's content-visibility result: 98% off initial layout, same
DOM. Layout mode is a rounding error; layout scope is the decision.
Container queries change what a component can be. Measured: a @container rule responded when
its container narrowed to 400 px while the viewport stayed at 1200 px; the equivalent @media rule
did nothing. That is not a performance difference, it is a capability difference — and it is
what makes genuinely reusable components possible (fe-38).
3. How it works
+==================================================================+
| SIZING: how much must the browser MEASURE? |
+==================================================================+
width: 200px -> no measurement (cheapest)
width: 20% -> depends on parent (one pass)
width: auto -> depends on context
width: max-content -> measure content, no wrap
width: fit-content -> min(max-content, available)
width: min-content -> measure longest unbreakable unit (dearest: 52.1ms vs 33.1ms)
+==================================================================+
| RESPONSIVE: what is the rule allowed to ask about? |
+==================================================================+
@media -> the VIEWPORT. A component cannot know it is in a sidebar.
@container -> the nearest ancestor with container-type.
Requires containment on that ancestor -- which is the cost.
.wrap { container-type: inline-size; } <- promises size containment
@container (min-width: 700px) { ... }
Measured
| layout mode (20,000 items) | initial layout | relayout |
|---|---|---|
| block | 55.1 ms | 23.5 ms |
| inline-block | 55.7 ms | 9.5 ms |
| flex | 59.3 ms | 7.3 ms |
| grid | 62.5 ms | 14.7 ms |
| float | 75.2 ms | 36.2 ms |
| absolute | 75.5 ms | 9.8 ms |
Spread: 1.4×.
| responsive strategy (8,000 items) | initial layout | initial style |
|---|---|---|
| none | 31.8 ms | 4.3 ms |
@media | 31.8 ms | 4.8 ms |
@container | 33.2 ms | 7.3 ms |
| container narrowed to 400 px, viewport unchanged | padding |
|---|---|
@container | 8px → 0px — responded |
@media | 8px → 8px — ignored |
4. Core terminology
| Term | Definition |
|---|---|
| Formatting context | The layout algorithm governing a box's children (block, inline, flex, grid) |
| Intrinsic sizing | Sizing from content: min-content, max-content, fit-content |
min-content | Width of the largest unbreakable unit; requires measuring every word |
| Containing block | The ancestor box a percentage or absolute offset resolves against |
| Stacking context | Isolated z-ordering scope; created by transform, opacity<1, contain: paint, … |
| Container query | @container; matches against an ancestor with container-type |
container-type: inline-size | Enables inline-axis container queries; implies size containment on that axis |
| Container query unit | cqw, cqh, cqi, cqb — relative to the query container |
| Subgrid | Child grid inheriting its parent's tracks, so nested content can align across items |
aspect-ratio | Reserves space before content loads; a CLS tool (fe-11) |
| Gap | Spacing that does not participate in the box model; works in flex, grid and multicol |
5. Mental models
Choose layout mode for expressiveness, not speed. The 1.4× spread means the question is which algorithm expresses your intent with the fewest workarounds. Grid for two-dimensional relationships, flex for one-dimensional distribution, block for flow. A layout that needs no wrapper divs and no magic numbers will outperform a "faster" one that needs both.
Sizing keywords are measurement requests. min-content costs 1.6× a fixed width because the
browser must measure every unbreakable unit. That is a real cost and usually the right trade —
fit-content and max-content measured close to fixed, and they remove entire classes of magic
number.
Container queries move the responsive boundary from the page to the component. A component that queries the viewport is not reusable: dropping it in a sidebar produces a layout designed for a main column. Container queries make "responsive" a property of the component rather than of the page, which is what a design system needs to be honest.
Containment is the price of a container query. container-type: inline-size implies size
containment on that axis, so the container's inline size may no longer depend on its contents.
Measured at +1.4 ms layout and +3.0 ms style over 8,000 items — cheap, but not free, and the
constraint matters more than the cost.
6. Common misconceptions
-
"Flex and grid are slow; use block or absolute." Measured backwards. Absolute was slowest overall (75.5 ms) with the highest style cost, and flex was fastest on relayout (7.3 ms).
-
"Absolute positioning avoids layout." It takes the element out of flow; it does not avoid layout. It measured worst here, partly because per-element inline positioning inflates style cost (27.7 ms vs ~11 ms).
-
"Intrinsic sizing is too expensive." 1.6× worst case, and only
min-contentis notably dearer.fit-contentandmax-contentmeasured within ~7% of a fixed width. -
"Container queries are expensive." +1.4 ms of layout across 8,000 items. The real cost is the containment constraint, not the query.
-
"Container queries replace media queries." They answer different questions. Page-level decisions — how many columns in the shell, whether a nav collapses — are viewport questions. Component-level decisions are container questions.
-
"Layout performance is about picking the right properties." fe-05 measured 98% off initial layout from
content-visibility. This module measured 1.4× across every layout mode. Scope dominates mode by two orders of magnitude.
7. Interview talking points
- "We measured six layout modes over 20,000 items and the spread was 1.4×, with absolute positioning slowest and flex fastest on relayout. Choosing layout mode for performance is optimising the wrong variable — layout scope is worth ~98%, mode is worth ~40%."
- "Container queries are a capability change, not a performance one. A component that queries the
viewport can't be reused in a sidebar. We verified it: narrowing the container to 400px changed
@containerstyles and left@mediauntouched at a 1200px viewport." - "The cost of a container query is
container-type, which implies size containment. That's a constraint on your layout, not a millisecond figure — the milliseconds were negligible." - "
min-contentis the one intrinsic keyword with a real cost, because the browser measures every unbreakable unit.fit-contentis nearly free and removes most magic numbers."
8. Connections to other modules
fe-05— direct comparison: containment/content-visibility(98%) versus layout mode (1.4×). Same pipeline stage, two orders of magnitude apart.fe-01— forced synchronous layout is what makes any of this expensive per frame.fe-11—aspect-ratioand explicit sizing are the primary CLS tools.fe-26(i18n) — logical properties, and whygap/gridsurvive RTL where margin hacks do not.fe-30— when layout scope genuinely cannot be reduced declaratively.fe-38— container queries are what make design-system components context-independent.browser-framework-internals.md§12–13 (Layout Engine) — cross for the algorithms themselves.