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 "adding container-type broke 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

DecisionQuery
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.