Skip to main content
CodeRocket
Performancemediummetrics

Reduce DOM size and complexity

rule · dom-size

The DOM (Document Object Model) is the browser's in-memory representation of your page. As the tree grows, every style recalculation, layout pass, and interaction has more work to do.

Code Examples

1. Simplify HTML Structure

Avoid "div-itis" (excessive nesting of div elements).

HTML
<!-- Bad: Excessive nesting -->
<div class="wrapper">
  <div class="container">
    <div class="inner">
      <p>Hello World</p>
    </div>
  </div>
</div>
 
<!-- Good: Clean structure -->
<article class="content">
  <p>Hello World</p>
</article>

2. Implement List Virtualization

Instead of rendering 1,000 rows, only render the visible window plus a small overscan buffer.

TSX
// Using react-window for a large list
import { FixedSizeList as List } from 'react-window';
 
const MyList = ({ items }) => (
  <List
    height={500}
    itemCount={items.length}
    itemSize={35}
    width={300}
  >
    {({ index, style }) => (
      <div style={style}>
        {items[index].name}
      </div>
    )}
  </List>
);

Why It Matters

  • Memory Usage: Every DOM node consumes memory. A massive DOM can lead to browser crashes or slow performance on low-end devices.
  • Style Calculation: When a CSS class is changed, the browser must re-evaluate styles for all affected nodes. More nodes mean more work.
  • Layout Performance: Complex DOM trees make "reflows" (re-calculating positions and sizes) much more expensive.
  • Interaction Latency: Large DOMs can cause lag when scrolling or clicking, negatively impacting metrics like Interaction to Next Paint (INP).

Diagnose the Real Bottleneck

A large DOM is not always the root problem. Confirm the page is paying for DOM work, not just network cost or oversized JavaScript.

You are likely dealing with a DOM-size problem when:

  • Lighthouse reports excessive node count or deep nesting
  • DevTools traces show expensive Recalculate Style or Layout
  • Scrolling, filtering, or expanding large views becomes sluggish
  • The route renders hundreds or thousands of repeated items at once

Remediation Order

  1. Remove unnecessary wrappers: flatten the markup before reaching for more advanced optimizations.
  2. Avoid hidden DOM bloat: do not keep large panels, menus, or tabs mounted if users cannot see them.
  3. Defer rendering: mount optional sections, drawers, and modals when needed instead of on first render.
  4. Paginate or virtualize: when repeated collections remain large, reduce how many rows exist at once.

Pass-Fail Guidance

  • Aim for fewer than roughly 1,500 total nodes on a typical page and a maximum depth below roughly 32.
  • Treat views rendering more than roughly 100-200 repeated items as candidates for pagination or virtualization.
  • If traces show layout or style work dominating scroll and interaction, reduce mounted nodes before micro-optimizing components.

Common Mistakes

  • Optimizing the DOM when the real issue is bundle size: node count is only one part of the page cost.
  • Keeping hidden UI mounted forever: invisible nodes still consume memory and style work.
  • Rendering full datasets by default: feeds, admin tables, and search results often need pagination or windowing.
  • Virtualizing too early: small lists do not need the complexity.
  • Breaking semantics while flattening markup: cleaner structure should still preserve headings, lists, and table meaning.

Tools & Validation

  • Lighthouse (opens in a new tab): Audits the "DOM size" and provides specific counts for nodes and depth.
  • Chrome DevTools Console: Run document.querySelectorAll('*').length to see the current node count.
  • Performance Panel: Record a trace to see if "Recalculate Style" or "Layout" are taking too long.

Standards

  • Use web.dev: Learn Performance as the standard for measuring the final production behavior, not just local synthetic output.
  • Use Chrome Developers: Lighthouse overview as the standard for measuring the final production behavior, not just local synthetic output.
  • Use Patterns.dev: List Virtualization as the standard for measuring the final production behavior, not just local synthetic output.

Verification

Automated Checks

  • Measure the affected page or flow in Lighthouse, PageSpeed Insights, or DevTools and confirm the targeted metric improves.
  • Inspect the network waterfall or performance timeline to confirm the intended resource or execution change actually took effect.

Manual Checks

  • Verify the change on a throttled mobile profile, not just local desktop.
  • If this rule maps to a budget or Web Vital, confirm the page now stays within that threshold.