Skip to main content
Beta: Front-End Checklist is currently in beta. Some issues are still being fixed. Thanks for your patience.

Reduce DOM size and complexity

Keep the DOM tree small and shallow to improve memory usage and rendering performance.

Utilities
Quick take
Typical fix time 10 min
  • Keep total DOM nodes below 1,500
  • Avoid deep nesting (maximum depth < 32)
  • Use virtualization for long lists of elements
Why it matters: An excessive DOM size increases memory usage, slows down style calculations, and makes layout reflows more expensive, leading to poor interaction performance.

Rule Details

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).

<!-- 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.

// 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 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.

Use with AI

Copy these prompts to use with your AI assistant, or install the MCP server to use directly from Claude, Cursor, or Windsurf.

Check

Verify implementation

Check the total number of DOM nodes and the maximum DOM depth using Lighthouse or Chrome DevTools.

Fix

Auto-fix issues

Simplify the HTML structure, remove unnecessary wrapper elements, and implement virtualization for large lists.

Explain

Learn more

Explain the performance impact of a large DOM tree on memory and rendering speed.

Review

Code review

Review the routes, assets, and loading behavior that affect Reduce DOM size and complexity. Flag exact files, requests, or rendering steps that add unnecessary network, CPU, or layout cost, and describe the measurement method used to confirm the issue.

Sources

References used to support the guidance in this rule.

Further Reading

Tools and supplementary material for exploring the topic in more depth.

PageSpeed Insights
pagespeed.web.devTool

Rules that often go hand-in-hand with this one.

Minimize critical request chains

Reduce the number and depth of dependent resource requests that block the initial rendering of the page.

Performance
Convert animated GIFs to video

Large animated GIFs are replaced with more efficient video formats like MP4 or WebM to reduce page weight.

Performance
Virtualize long lists and tables

Render only the visible subset of rows or cards in large collections to reduce DOM size, memory usage, and scroll-time rendering work.

Performance
Remove duplicate JavaScript libraries

Detect and consolidate duplicate JavaScript libraries to reduce bundle size and prevent version conflicts.

Performance

Was this rule helpful?

Your feedback helps improve rule quality. This stays internal for now.

Loading feedback...
0 / 385