Web & Networking › How Browsers Work
Layout / Reflow
Computing the position and size of every element.
Also known as: layout, reflow, layout thrashing
Layout (reflow) computes every visible element’s geometry — position and size — from styles and content. It’s the pipeline’s expensive step: deeply interdependent (one element’s size shifts siblings and ancestors), so repeating it costs far more than repeating paint. Forced synchronous layout — reading geometry right after mutating styles — is the classic jank source.
mutate style → read offsetHeight → forced reflow (sync!)
repeat per row → layout thrashing: N reflows for N rows
The browser batches layout work when left alone; interleaved read/write forces it to flush the queue on every read. A loop touching a hundred rows can trigger a hundred full layouts.
The classic mistakes:
- Layout thrashing. The read-write loop above. Fix: read all, then write all (batch phases), or use
requestAnimationFrameto schedule mutations. - Animating layout properties. Animating
width,top,marginre-runs layout every frame. Animatetransformandopacityinstead — compositor-only, no layout. - Unnecessary deep reflows. Changing an ancestor’s width re-lays-out its whole subtree. Contain the damage: size leaves, not roots; use CSS containment where supported.
- Forced sync layout in frameworks. Render-then-measure-then-patch patterns in effects re-trigger what the framework just computed. Measure in layout effects deliberately, mutate minimally.
- Ignoring the initial layout. A huge DOM lays out slowly on first paint too — not just on updates. DOM size is a layout budget.
- Display:none vs visibility.
display: noneremoves from layout entirely (cheap to hide, full reflow to show);visibility: hiddenkeeps geometry (no reflow). Choose by whether the space should persist.
The discipline: batch reads before writes, animate compositor properties, keep DOM lean, and contain layout scope. Reflow is necessary — repeated reflow is optional.