Step 1 — What the Browser Is Allowed to Skip

Goal

Establish that rendering cost is a property of your CSS instructions, not your DOM size — and distinguish two tools that are constantly confused.

Predict first

3,000 cards × 12 rows = 261,011 DOM nodes, in a 1200×800 viewport. Three variants: no containment, content-visibility: auto, contain: strict.

Predict initial layout time for each. Then predict which of the two containment variants helps initial render more, and by how much.

Run

cd src && npm install && npm run containment

Expected output:

  variant                    | DOM nodes | initial style | initial layout
  no containment             |    261011 |    99.5ms     |   401.9ms
  content-visibility: auto   |    261011 |    10.9ms     |     7.9ms
  contain: strict            |    261011 |    89.6ms     |   398.4ms

What just happened

content-visibility: auto cut initial layout by 98% — 401.9 ms to 7.9 ms — with an identical node count, no JavaScript, and one declaration. The DOM was never the problem.

contain: strict did essentially nothing (398.4 vs 401.9 ms). This is the more important half.

The two solve different problems, and conflating them is the most common containment mistake:

QuestionTool
"Most of this is offscreen — may the browser skip it?"content-visibility: auto
"A change inside this box must not disturb the page"contain: layout (+ size)

A team that adds contain expecting content-visibility's effect measures no improvement and concludes containment is useless. The measurement is what prevents that.

Always pair content-visibility: auto with contain-intrinsic-size. Without it, skipped subtrees measure as zero height: wrong scrollbar, jumping scroll position. contain-intrinsic-size: auto 240px says "assume 240px until you know better, then remember."

Try before continuing

CARDS=200 npm run containment

The advantage should shrink or vanish — everything now fits near the viewport, so there is nothing to skip. Being able to predict that is the checkpoint, not the original number.

Checkpoint

docs/verification.md Checkpoints 1 and 2.