Measured Results
Chrome for Testing 149.0.7827.55 (arm64), viewport 1200×800, Performance.getMetrics deltas with a
two-rAF + forced-layout settle. Fresh page per variant. Reproduce: cd ../src && npm run all.
1. Layout modes — 20,000 items, identical content and visual result
| mode | initial layout | initial style | relayout (width change) |
|---|---|---|---|
| block | 55.1 ms | 11.7 ms | 23.5 ms |
| inline-block | 55.7 ms | 11.3 ms | 9.5 ms |
| flex | 59.3 ms | 11.3 ms | 7.3 ms |
| grid | 62.5 ms | 10.5 ms | 14.7 ms |
| float | 75.2 ms | 11.0 ms | 36.2 ms |
| absolute | 75.5 ms | 27.7 ms | 9.8 ms |
Spread: 1.4×. Fastest initial: block. Slowest: absolute.
Three results that contradict common advice:
- Absolute positioning was slowest, and carried 2.4× the style cost of every other mode — the
per-element inline
left/topdeclarations. "Take it out of flow to make it fast" does not hold. - Flex was fastest on relayout (7.3 ms), beating block (23.5 ms) by 3.2×.
- Float was second-slowest on both measures, and is the mode most often retained for compatibility reasons.
Compare against fe-05: content-visibility cut initial layout by 98%. Layout mode spans
1.4×. Scope dominates mode by two orders of magnitude.
2A. Intrinsic sizing — 8,000 items
width | initial layout | relayout |
|---|---|---|
200px | 33.1 ms | 1.5 ms |
20% | 31.9 ms | 14.6 ms |
min-content | 52.1 ms | 2.1 ms |
max-content | 35.4 ms | 1.4 ms |
fit-content | 35.2 ms | 1.7 ms |
auto | 33.9 ms | 9.5 ms |
Spread: 1.6×. Only min-content is notably expensive — the browser must measure the longest
unbreakable unit in every box. fit-content and max-content land within ~7% of a fixed width.
Note the relayout column inverts the picture: 20% and auto are dearest to re-lay-out (14.6 ms,
9.5 ms) because they depend on the parent, while the intrinsic keywords are nearly free once
measured.
2B. Container queries vs media queries — 8,000 items
| strategy | initial layout | initial style | relayout |
|---|---|---|---|
| none | 31.8 ms | 4.3 ms | 9.1 ms |
@media | 31.8 ms | 4.8 ms | 9.7 ms |
@container | 33.2 ms | 7.3 ms | 9.3 ms |
Container queries cost +1.4 ms layout and +3.0 ms style over 8,000 elements.
The behavioural result — the reason they exist
Container narrowed to 400 px, viewport unchanged at 1200 px:
| padding before | padding after | |
|---|---|---|
@container (min-width: 700px) | 8px | 0px — responded |
@media (min-width: 700px) | 8px | 8px — ignored |
The media query cannot see the container. A component styled with media queries produces a main-column layout when dropped into a sidebar, and there is no way to fix it from inside the component. That is a capability gap, not a performance one.
The real cost is the constraint: container-type: inline-size implies size containment on the
inline axis, so the container's width may no longer be derived from its contents.