Skip to content
intermediatePhase 34 · DOM

DOM Performance

Optimize DOM operations: batch updates, document fragments, and virtual scrolling.

45m
0 problems
Topic Progress0%

Minimizing Reflows

Reflows happen when the browser recalculates layout. They're expensive and should be minimized.

What Triggers Reflow

// Reading layout properties triggers reflow
const width = element.offsetWidth;
const height = element.offsetHeight;
const rect = element.getBoundingClientRect();
const computed = window.getComputedStyle(element);

// Writing layout properties triggers reflow
element.style.width = '100px';
element.style.height = '200px';
element.style.position = 'absolute';

Layout Thrashing

// BAD: Alternating reads and writes
for (let i = 0; i < 100; i++) {
  element.style.width = `${i}px`; // Write
  console.log(element.offsetWidth); // Read - forces layout!
}

// GOOD: Batch reads, then batch writes
const width = element.offsetWidth; // Read once
for (let i = 0; i < 100; i++) {
  element.style.width = `${width + i}px`; // Write
}

Minimize DOM Changes

// BAD: Multiple individual changes
document.body.appendChild(newDiv1);
document.body.appendChild(newDiv2);
document.body.appendChild(newDiv3);

// GOOD: Single batch change
const fragment = document.createDocumentFragment();
fragment.appendChild(newDiv1);
fragment.appendChild(newDiv2);
fragment.appendChild(newDiv3);
document.body.appendChild(fragment); // Single reflow

Use CSS Classes

// BAD: Multiple style changes
element.style.color = 'red';
element.style.backgroundColor = 'blue';
element.style.fontSize = '16px';
element.style.padding = '10px';

// GOOD: Single class change
element.classList.add('active-state');

/* CSS handles the rest */
.active-state {
  color: red;
  background-color: blue;
  font-size: 16px;
  padding: 10px;
}

Document Fragments

DocumentFragment is a lightweight container for building DOM trees offline.

Why Fragments?

// BAD: Each appendChild triggers reflow
const list = document.querySelector('ul');
for (let i = 0; i < 1000; i++) {
  const li = document.createElement('li');
  li.textContent = `Item ${i}`;
  list.appendChild(li); // 1000 reflows!
}

// GOOD: Fragment batches updates
const fragment = document.createDocumentFragment();
for (let i = 0; i < 1000; i++) {
  const li = document.createElement('li');
  li.textContent = `Item ${i}`;
  fragment.appendChild(li); // No reflow yet!
}
list.appendChild(fragment); // 1 reflow!

Creating Fragments

// Method 1: DocumentFragment
const fragment = document.createDocumentFragment();

// Method 2: Template element
const template = document.querySelector('#item-template');
const clone = template.content.cloneNode(true);
document.body.appendChild(clone);

// Method 3: Template literal
const html = `
  <div class="item">
    <h2>Title</h2>
    <p>Content</p>
  </div>
`;
const temp = document.createElement('div');
temp.innerHTML = html;
const fragment = temp.firstElementChild;

Practical Example

function renderList(items) {
  const list = document.querySelector('#list');
  const fragment = document.createDocumentFragment();
  
  items.forEach(item => {
    const li = document.createElement('li');
    li.dataset.id = item.id;
    li.innerHTML = `
      <span class="name">${item.name}</span>
      <button class="delete">X</button>
    `;
    fragment.appendChild(li);
  });
  
  // Single DOM update
  list.innerHTML = ''; // Clear list
  list.appendChild(fragment); // Add all items
}

Cloning Nodes

const original = document.querySelector('.item');

// Shallow clone (no children)
const shallow = original.cloneNode(false);

// Deep clone (with children)
const deep = original.cloneNode(true);

// Add to DOM
document.body.appendChild(deep);

Virtual Scrolling

Virtual scrolling renders only visible items, essential for large lists.

The Problem

// Rendering 10,000 items is slow and memory-intensive
const items = Array.from({ length: 10000 }, (_, i) => ({
  id: i,
  name: `Item ${i}`
}));

// This is terrible for performance!
items.forEach(item => {
  const li = document.createElement('li');
  li.textContent = item.name;
  list.appendChild(li);
});

Basic Virtual Scroll Implementation

class VirtualScroll {
  constructor(container, items, itemHeight = 30) {
    this.container = container;
    this.items = items;
    this.itemHeight = itemHeight;
    this.visibleCount = Math.ceil(container.clientHeight / itemHeight);
    
    // Create scroll container
    this.scrollContent = document.createElement('div');
    this.scrollContent.style.height = `${items.length * itemHeight}px`;
    this.scrollContent.style.position = 'relative';
    
    // Create visible container
    this.visibleContainer = document.createElement('div');
    this.visibleContainer.style.position = 'absolute';
    this.visibleContainer.style.width = '100%';
    
    this.scrollContent.appendChild(this.visibleContainer);
    this.container.appendChild(this.scrollContent);
    
    // Listen for scroll
    this.container.addEventListener('scroll', () => this.render());
    this.render();
  }
  
  render() {
    const scrollTop = this.container.scrollTop;
    const startIndex = Math.floor(scrollTop / this.itemHeight);
    const endIndex = Math.min(startIndex + this.visibleCount, this.items.length);
    
    // Update position
    this.visibleContainer.style.top = `${startIndex * this.itemHeight}px`;
    
    // Render only visible items
    this.visibleContainer.innerHTML = '';
    for (let i = startIndex; i < endIndex; i++) {
      const div = document.createElement('div');
      div.style.height = `${this.itemHeight}px`;
      div.textContent = this.items[i].name;
      this.visibleContainer.appendChild(div);
    }
  }
}

// Usage
const container = document.querySelector('#scroll-container');
const virtualScroll = new VirtualScroll(container, items, 30);

Windowing Libraries

// Popular virtual scrolling libraries:
// - react-window
// - react-virtualized
// - vue-virtual-scroll-list
// - tanstack-virtual

// React example with react-window
import { FixedSizeList } from 'react-window';

const Row = ({ index, style }) => (
  <div style={style}>
    Item {index}
  </div>
);

const VirtualList = () => (
  <FixedSizeList
    height={500}
    width="100%"
    itemCount={10000}
    itemSize={35}
  >
    {Row}
  </FixedSizeList>
);

Practice Problems

0/3solved
Build DOM Performance Component

Create a reusable React component implementing DOM Performance. Include proper state management and accessibility.

Solution
// Production-ready component with:
// - Proper TypeScript types
// - Accessibility (ARIA)
// - Error boundaries
// - Loading states
// - Memoization where needed
DOM Performance Testing

Write unit and integration tests for DOM Performance using React Testing Library.

Solution
// Test coverage:
// 1. Rendering tests
// 2. Interaction tests
// 3. Edge case tests
// 4. Accessibility tests
DOM Performance Performance

Optimize DOM Performance for performance. Consider memoization, code splitting, and bundle size.

Solution
// Optimization techniques:
// 1. React.memo / useMemo / useCallback
// 2. Code splitting with lazy()
// 3. Virtual scrolling for lists
// 4. Image lazy loading
// 5. Bundle analysis

Quiz

1. What is layout thrashing?

Question 1 options

2. What is a DocumentFragment?

Question 2 options

3. Why use virtual scrolling?

Question 3 options

4. How do you minimize DOM reflows?

Question 4 options

Flashcards

Question

What is layout thrashing?

Answer

Alternating DOM reads and writes that force the browser to recalculate layout multiple times.

Question

What is a DocumentFragment?

Answer

A lightweight container for building DOM trees offline. Adding to it doesn't trigger reflows.

Question

What is virtual scrolling?

Answer

A technique that renders only visible items in a large list, improving performance.

Question

How to batch DOM updates?

Answer

Use DocumentFragment or string building, then add to DOM once. Avoid alternating reads/writes.

Question

What is DOM Performance?

Answer

DOM Performance is a key concept in frontend development.

Revision Notes

Key Takeaways

  • 1.Minimize DOM reads and writes to reduce reflows
  • 2.DocumentFragment allows offline DOM building
  • 3.Virtual scrolling is essential for large lists
  • 4.CSS classes are more performant than inline styles
  • 5.Batch DOM operations for better performance

Interview Tips

  • Explain layout thrashing and how to avoid it
  • Show how to use DocumentFragment for batch updates
  • Discuss virtual scrolling implementation
  • Explain when to use DocumentFragment vs innerHTML

Cheat Sheet

DOM Performance Cheat Sheet

Minimizing Reflows

  • Batch reads and writes
  • Use CSS classes instead of inline styles
  • Use DocumentFragment for batch updates

DocumentFragment

const frag = document.createDocumentFragment();
frag.appendChild(el1);
frag.appendChild(el2);
document.body.appendChild(frag); // Single reflow

Layout Thrashing

// BAD
for (i) { write(); read(); }

// GOOD
const val = read();
for (i) { write(val); }

Virtual Scrolling

  • Render only visible items
  • Essential for 1000+ items
  • Use libraries like react-window