Summary
Interleaving DOM reads (offsetWidth, getBoundingClientRect) with writes forces synchronous layout recalc — "layout thrashing." Batch reads then writes; use requestAnimationFrame for visual updates. Virtual DOM doesn't protect against forced sync layout in refs/measurements. DevTools Performance shows "Recalculate Style" / "Layout" spikes.
Code example
// Bad: read-write-read-write forces layout thrashing
elements.forEach((el) => {
el.style.width = el.offsetWidth + 10 + 'px';
});
// Good: batch reads, then writes
const widths = elements.map((el) => el.offsetWidth);
elements.forEach((el, i) => {
el.style.width = widths[i] + 10 + 'px';
});
Key points
- Interleaving DOM reads (offsetWidth, getBoundingClientRect) with writes forces synchronous layout recalc — "layout thrashing." Batch reads then writes; use
requestAnimationFramefor visual updates. - Virtual DOM doesn't protect against forced sync layout in refs/measurements.
- DevTools Performance shows "Recalculate Style" / "Layout" spikes.