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

modeinitial layoutinitial stylerelayout (width change)
block55.1 ms11.7 ms23.5 ms
inline-block55.7 ms11.3 ms9.5 ms
flex59.3 ms11.3 ms7.3 ms
grid62.5 ms10.5 ms14.7 ms
float75.2 ms11.0 ms36.2 ms
absolute75.5 ms27.7 ms9.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/top declarations. "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

widthinitial layoutrelayout
200px33.1 ms1.5 ms
20%31.9 ms14.6 ms
min-content52.1 ms2.1 ms
max-content35.4 ms1.4 ms
fit-content35.2 ms1.7 ms
auto33.9 ms9.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

strategyinitial layoutinitial stylerelayout
none31.8 ms4.3 ms9.1 ms
@media31.8 ms4.8 ms9.7 ms
@container33.2 ms7.3 ms9.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 beforepadding after
@container (min-width: 700px)8px0px — responded
@media (min-width: 700px)8px8px — 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.