c
Overview
Stop touching the DOM!

Stop touching the DOM!

February 26, 2025
2 min read

DOM operations are expensive. If you care about performance in JavaScript, one of the first rules is simple:

Touch the DOM as little as possible.

It might sound dramatic, but there’s solid reasoning behind it.

Why DOM Operations Are Expensive

When you manipulate the DOM, the browser often needs to recalculate layout and repaint the screen. This process is called reflow (also known as layout).

What is reflow?

Reflow happens when changes to the DOM affect the layout of the page. For example:

  • Changing the width or height of an element
  • Adding or removing elements
  • Updating text content
  • Modifying CSS that affects layout

When you do any of these, the browser may need to:

  1. Recalculate element positions and dimensions
  2. Repaint pixels on the screen

This is computationally expensive — especially when done repeatedly in a loop.

The classic performance mistake

Let’s say you want to append 100 <div> elements.

A naive implementation:

const container = document.getElementById("container");
for (let i = 0; i < 100; i++) {
const div = document.createElement("div");
div.textContent = `Item ${i}`;
container.appendChild(div);
}

You’re touching the DOM 100 times.

Even though browsers optimize internally, you’re still increasing layout work and potential reflows.

Explanation

It’s like going to the store 100 times to buy 100 items instead of buying everything in one trip.

The solution: DocumentFragment

DocumentFragment lets you build DOM nodes off-screen, then append them in a single operation.

const container = document.getElementById("container");
const fragment = document.createDocumentFragment();
for (let i = 0; i < 100; i++) {
const div = document.createElement("div");
div.textContent = `Item ${i}`;
fragment.appendChild(div);
}
container.appendChild(fragment);

Now the browser does layout work once instead of potentially 100 times.

Batch your changes. Touch the DOM once.

How does this compare to React?

If you’re using React, things work differently.

React Doesn’t Use the Real DOM Directly

React introduces something called the Virtual DOM.

Instead of updating the real DOM immediately:

  1. React creates a lightweight in-memory representation (Virtual DOM).
  2. When state changes, React calculates the difference (diffing).
  3. React updates the real DOM only where necessary.

This batching behavior happens automatically.

So… Do you need DocumentFragment in React?

Short answer:

If you’re using React properly, you usually don’t need to manually optimize DOM updates with DocumentFragment.

React already:

  • Batches updates
  • Minimizes real DOM mutations
  • Re-renders efficiently at the component level

When you write:

{items.map(item => (
<div key={item.id}>{item.name}</div>
))}

React handles the batching and diffing internally.

You’re not directly touching the DOM 100 times — React calculates the minimal changes and applies them efficiently.

When this still matters

Even in React, performance awareness is important:

  • Avoid unnecessary re-renders
  • Use proper keys in lists
  • Memoize when appropriate
  • Avoid heavy synchronous layout reads

But you generally don’t need to think about DocumentFragment or manual batching.

React already does that for you.

Conclusion

At the end of the day, DOM performance isn’t about clever tricks — it’s about understanding how browsers work.

Every time you touch the DOM, the browser may need to recalculate layout and repaint the screen. Do that once? No problem. Do it a hundred times in a loop? Now you’re paying for it.