DOM size and rendering: when a page has too much

A large DOM slows every style and layout update. What Lighthouse flags, how to measure yours, and how to cut the cost with less markup and content-visibility.

IntermediateExplainer6 min readUpdated October 30, 2026

In this guide
  1. What the DOM is, and why size matters
  2. What Lighthouse reports
  3. How to measure your own page
  4. Where big DOMs come from
  5. Reduce the DOM
  6. Skip the rendering of off-screen content
  7. Make updates cheaper
  8. Check the result
  9. Check your own page
  10. Sources

What the DOM is, and why size matters

When the browser reads your HTML it builds a tree of nodes called the Document Object Model, the DOM. Every tag becomes a node. Scripts and styles then work on that tree. MDN notes that the greater the number of nodes, the longer the following steps of rendering take, and that a few extra nodes do not make a difference but many extra nodes do.

The Lighthouse documentation for the older DOM check names three costs:

web.dev explains the runtime cost. Style calculation, in the worst case, costs the number of elements multiplied by the number of style rules, because each element must be checked against each rule. Layout is almost always scoped to the whole document, so more elements generally mean more expensive layout. Both feed into Interaction to Next Paint, because the next frame cannot be drawn until style and layout are done.

What Lighthouse reports

The older Lighthouse audit warned when the body held more than about 800 nodes and failed it above about 1,400. Many people still quote those numbers. In Lighthouse 13.5 the audit is replaced by an insight called Optimize DOM size, and it works differently.

It looks for slow updates. A layout that took 40 milliseconds or more and touched more than 100 objects, or a style recalculation that took 40 milliseconds or more and affected more than 300 elements, is reported. The insight lists the five longest such updates, with the number of objects or elements each one involved, and it shows three facts about the DOM: the total number of elements, the greatest depth and the element with the most children. A page with no such updates passes, and the insight is informational, not a score.

The change makes sense. A page with 3,000 elements that never changes is cheap. A page with 1,000 elements that rebuilds a third of them on every click is not.

How to measure your own page

Count the elements. Paste this into the console to get the total and the greatest depth:

const all = document.querySelectorAll('*');
let maxDepth = 0;
for (const el of all) {
  let depth = 0;
  for (let n = el; n; n = n.parentElement) depth++;
  if (depth > maxDepth) maxDepth = depth;
}
console.log({ elements: all.length, maxDepth });

Find the expensive updates. Record an interaction in the Performance panel of Chrome DevTools. Look for the purple blocks named Recalculate Style and Layout. Click one. For a style recalculation DevTools tells you how many elements were affected and how long it took, and for a layout it shows the size of the tree and how many nodes needed layout. In web.dev's examples, a style recalculation of just over 25 milliseconds affected about 900 elements, and a layout over 28 milliseconds touched 5 nodes in a tree of 1,618 elements. If you can reduce either number, the work gets cheaper.

Check where the nodes come from. Right-click the element in the Elements panel and look at its parents. Long chains of wrapper elements are easy to spot.

Where big DOMs come from

Reduce the DOM

The Lighthouse advice is to create nodes only when they are needed, and to remove them when they are not. In practice:

  1. Load pieces on demand. If you load the page and note which nodes are shown, you can often move the hidden ones out of the first document and create them after a scroll or click.
  2. Page or window long lists. Show 20 to 50 items and add more on request, or draw only the rows in view. For Angular, Lighthouse points to virtual scrolling in the CDK, and for React to a windowing library such as react-window.
  3. Use one version of the markup. Let CSS rearrange one set of elements for each screen size, instead of two hidden copies.
  4. Flatten wrappers. An element that only exists to hold another can often go.
  5. Remove what is never used. Hidden elements still count.

Skip the rendering of off-screen content

The CSS property content-visibility: auto tells the browser it may skip the layout and painting of an element until it is near the screen. MDN says it turns on layout, style and paint containment for the element, and when the element is not relevant to the visitor it skips its contents. The content stays in the DOM and in the accessibility tree, and it can still be found with find-in-page and reached with the keyboard.

section {
  content-visibility: auto;
  contain-intrinsic-size: auto 500px;
}

The second line gives each skipped section a stand-in height of 500 pixels, so that the scrollbar does not jump when sections are drawn. With the word auto, the browser remembers the real size after it has drawn the section once. Use a value near the real height of your sections.

Support: content-visibility works in Chrome 85, Firefox 125 and Safari 18, and contain-intrinsic-size in Chrome 83, Firefox 107 and Safari 17. A browser that does not know the property ignores it, and the page works as before. Test the sections, because their contents are not laid out until they are close to the screen, which matters for scripts that measure them and for links that jump to them.

content-visibility: hidden is the other value. It skips the contents completely and keeps the rendering state, so showing the element again is faster than with display: none. It suits panels that open and close.

Make updates cheaper

Check the result

  1. Run the count again, and record the same interaction in the Performance panel. The events should be shorter, and the numbers of elements and nodes should be smaller.
  2. Test the sections that use content-visibility, including the scroll position, anchor links and keyboard navigation.
  3. Watch Interaction to Next Paint in the field over the following weeks.

Check your own page

Run the free audit and look at Optimize DOM size and Forced reflow in the insights. If neither appears, your DOM is not the problem and your time is better spent elsewhere. If they do, the lists show the biggest updates, which is where to start. For the other kinds of main-thread work, see reduce main-thread work.

Sources

Start here

Free website audit

Live Google data for any public page: mobile and desktop.

Mobile + desktop · Lighthouse lab test · Real-user Chrome data when Google has it

Rather have this done for you? Speed optimization · Book a call

Related guides

All guides →