Rendering performance · interactive
Layout Thrashing Lab
Tick a box to inject a specific rendering anti-pattern into a live animation loop, then watch it show up in the frame metrics. Everything runs on your machine, calibrated to your display's real refresh rate.
1 · The browser batches layout
Changing the DOM does not recompute anything. A write just marks layout dirty — the plan is to recompute geometry once, right before the next paint, no matter how many writes your code makes. Clean layout is cached and free to read. Dirty layout is a promise to recompute later.
2 · Reads turn "later" into "right now"
Ask for a geometry value — offsetHeight, getBoundingClientRect, getComputedStyle — while layout is dirty, and the browser must reflow synchronously to answer truthfully. In a loop that is N reflows per frame instead of one. The fix never changes: batch every read, then every write. One pair on one element is a rounding error; the scale is the whole difference.
3 · Expensive frames, and a meter that can lie
transform and opacity ride the compositor. top, left, width and margin re-run layout every frame; big shadows and blur re-paint every frame — on the compositor thread, where a main-thread FPS meter cannot see the cost. Always know which thread your metric is watching.