How do you make DOM updates fast?
By FrontendPro Editorial Team Updated 9/26/2026
Answer
DOM operations are not slow in themselves. What costs time is forcing the browser to recalculate layout, and doing it repeatedly.
Avoid layout thrashing
The browser batches style changes and applies them later. But reading a geometric property — offsetHeight, getBoundingClientRect(), scrollTop — forces it to flush everything pending right now so the answer is accurate. Alternating reads and writes in a loop therefore triggers a full layout on every iteration:
// slow — one forced layout per item
for (const el of items) {
el.style.height = el.offsetHeight + 10 + "px";
}
// fast — read everything, then write everything
const heights = items.map((el) => el.offsetHeight);
items.forEach((el, i) => (el.style.height = heights[i] + 10 + "px"));
This single change is usually the largest win available.
Batch insertions
Appending in a loop touches the live DOM each time. Build off-screen and insert once:
const frag = document.createDocumentFragment();
for (const item of data) frag.append(renderRow(item));
list.append(frag);
Other things that matter
- Animate
transformandopacity, nottop/left/width. Those two are handled by the compositor and skip layout and paint entirely. - Schedule visual work in
requestAnimationFrameso it runs once per frame instead of several times. - Cache lookups. Query once, reuse the reference; do not call
querySelectorinside a loop. - Throttle scroll and resize handlers, or better, replace them with
IntersectionObserverandResizeObserver, which fire only when something actually changed. - Render long lists virtually — put only the visible rows in the DOM.
Measure before optimising
Open the Performance panel and look for purple layout bars, or the "forced reflow" warnings. Rewriting code that was never the bottleneck is the most common wasted effort here — and note that a virtual DOM does not remove these rules, it just batches the writes for you.
