Step 2 — Intrinsic Sizing and Container Queries
Goal
Price intrinsic sizing, then establish that container queries are a capability change rather than a performance one.
Predict first
A. 8,000 items sized by 200px, 20%, min-content, max-content, fit-content, auto.
Which is dearest, and by how much?
B. The same list with no responsive rule, a @media (min-width: 700px) rule, and a
@container (min-width: 700px) rule. What does the container query cost?
C. The container is narrowed to 400 px while the viewport stays at 1200 px. What happens to each rule?
Run
npm run sizing
Expected output:
width value | initial layout | relayout
fixed | 33.1ms | 1.5ms
min-content | 52.1ms | 2.1ms
fit-content | 35.2ms | 1.7ms
auto | 33.9ms | 9.5ms
spread: 1.6x
strategy | initial layout | initial style
none | 31.8ms | 4.3ms
media | 31.8ms | 4.8ms
container | 33.2ms | 7.3ms
BEHAVIOUR — container narrowed to 400px, VIEWPORT unchanged at 1200px:
@container padding: 8px -> 0px responded to the CONTAINER
@media padding: 8px -> 8px ignored it
What just happened
Only min-content is expensive (1.6×) — the browser must measure the longest unbreakable unit
in every box. fit-content and max-content are within ~7% of a fixed width, so most magic-number
removal is nearly free.
The relayout column inverts it: % (14.6 ms) and auto (9.5 ms) are dearest to re-lay-out
because they depend on the parent. Intrinsic keywords are nearly free once measured.
Container queries cost +1.4 ms of layout over 8,000 elements — negligible.
And they do something media queries structurally cannot. The media query could not see the container narrow, because the viewport never changed. A component styled with media queries produces a main-column layout when dropped into a sidebar, and no amount of care inside the component fixes it.
The real cost is the constraint, not the milliseconds
container-type: inline-size implies size containment on the inline axis: the container's
inline size may no longer depend on its contents.
- A wrapper sized by its content (
fit-content, floated, inline-block) changes behaviour when it becomes a container. This reads as "addingcontainer-typebroke my layout" — it is the promise being enforced. - A container cannot query itself. That circularity is exactly why containment is required.
Practical rule: put container-type on a wrapper with an externally-determined width, and query
it from the component inside.
Media queries are not obsolete
| Decision | Query |
|---|---|
| page shell columns, nav collapse, print | @media |
prefers-reduced-motion, prefers-color-scheme, forced-colors | @media |
| card stacks vs sits horizontally | @container |
Page-level composition is a viewport question; component internals are a container question.
Checkpoint
docs/verification.md Checkpoints 3, 4 and 5.