Quiz

How can you optimize DOM manipulation for better performance?

Topics
Web APIsJavaScriptPerformance

TL;DR

Measure with browser performance tools, then reduce unnecessary DOM work, batch related mutations, keep DOM trees manageable, and avoid forced synchronous layout by grouping reads before writes. Build detached subtrees before inserting them, and use requestAnimationFrame() for visual updates. A framework or virtual DOM changes the programming model and may batch work, but it is not an automatic performance optimization.


How can you optimize DOM manipulation for better performance?

Minimize direct DOM access

DOM access is not inherently a problem, but repeated queries and mutations can become costly when they trigger style, layout, paint, or large tree updates. Reuse stable references where that improves clarity and avoids repeated work.

// Creating an element for the example below
const newElement = document.createElement('div');
newElement.id = 'myElement';
document.body.appendChild(newElement);
const element = document.getElementById('myElement'); // Access once
// Then use the reference to edit style
element.style.color = 'red';
element.style.backgroundColor = 'blue';
console.log(document.body); // Notice the edits

Batch DOM changes

Instead of making multiple changes to the DOM one at a time, batch them together. This reduces the number of reflows and repaints.

// Creating an element for the example below
const newElement = document.createElement('div');
newElement.id = 'myElement';
document.body.appendChild(newElement);
const element = document.getElementById('myElement');
element.style.cssText = 'color: red; background-color: blue;';
console.log(document.body); // Notice the edits

Use DocumentFragment

When adding multiple elements to the DOM, use a DocumentFragment to minimize reflows and repaints.

const fragment = document.createDocumentFragment();
for (let i = 0; i < 100; i++) {
const newElement = document.createElement('div');
newElement.textContent = `Item ${i}`;
fragment.appendChild(newElement);
}
document.body.appendChild(fragment);
console.log(document.body); // Notice that the divs have been added

Frameworks and virtual DOMs

Libraries such as React provide declarative rendering and can batch updates. Their reconciliation also adds JavaScript and memory overhead, so use a framework for application architecture and measure hot paths rather than assuming its virtual representation is faster than focused DOM code.

import React from 'react';
import { createRoot } from 'react-dom/client';
const App = () => (
<div>
<h1>Hello, world!</h1>
</div>
);
const root = createRoot(document.getElementById('root'));
root.render(<App />);

Use requestAnimationFrame for animations

For smoother animations, use requestAnimationFrame to ensure updates are synchronized with the browser's repaint cycle.

function animate() {
// Update animation state
requestAnimationFrame(animate);
}
requestAnimationFrame(animate);

Avoid layout thrashing

Layout thrashing occurs when you read and write to the DOM repeatedly in a way that forces the browser to recalculate styles and layout multiple times. To avoid this, separate read and write operations.

// Creating an element for the example below
const newElement = document.createElement('div');
newElement.id = 'myElement';
document.body.appendChild(newElement);
const element = document.getElementById('myElement');
const height = element.clientHeight; // Read
element.style.height = `${height + 10}px`; // Write

Further reading

Exercises

Check your understanding
Beta
Check your understanding Exercise
Check your understanding Exercise

Which changes can reduce avoidable DOM and layout work? Select all that apply.