const boxes = document.querySelectorAll(".box");
for (const box of boxes) {
const width = box.parentElement.offsetWidth;
box.style.width = width / 2 + "px";
}
Layout thrashing is when code switches back and forth between writing to the DOM and reading layout. It is also called forced synchronous layout.
Why is this slow? Properties like offsetWidth, getBoundingClientRect or scrollTop need up-to-date layout. After a style write, the layout is out of date. So the browser has to run layout right away, instead of once at the end of the frame.
In this code, every loop iteration writes a width. Then the next iteration reads offsetWidth. That read forces a new layout each time. With many boxes, this costs one layout per element.
The fix is to batch: do all the reads first, then all the writes. For example:
- First loop: map the boxes to their parent widths.
- Second loop: set the styles.
In larger apps, you can schedule writes in requestAnimationFrame. You can also use a read/write scheduler, so reads and writes from different components don't mix.
- Reading layout right after a write forces the browser to run layout immediately.
- Mixing reads and writes in a loop causes one layout per iteration.
- Batch all the reads first, then do all the writes.
requestAnimationFramehelps you schedule writes.