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 StyleorLayout - Scrolling, filtering, or expanding large views becomes sluggish
- The route renders hundreds or thousands of repeated items at once
Remediation Order
- Remove unnecessary wrappers: flatten the markup before reaching for more advanced optimizations.
- Avoid hidden DOM bloat: do not keep large panels, menus, or tabs mounted if users cannot see them.
- Defer rendering: mount optional sections, drawers, and modals when needed instead of on first render.
- Paginate or virtualize: when repeated collections remain large, reduce how many rows exist at once.
Pass-Fail Guidance
- Aim for fewer than roughly
1,500total nodes on a typical page and a maximum depth below roughly32. - Treat views rendering more than roughly
100-200repeated 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('*').lengthto 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.