Document Object Model (DOM): Definition, Tree, Manipulation

The DOM is the browser's tree representation of an HTML document. JavaScript reads + manipulates the DOM to update pages dynamically.

What is the Document Object Model (DOM)?

The Document Object Model (DOM) is the browser's in-memory representation of an HTML (or XML) document, structured as a tree of nodes. Every HTML element, attribute, and piece of text becomes a node. JavaScript uses the DOM API to read the structure, modify it, and respond to user events — that's how dynamic web pages work.

The DOM is a W3C standard, implemented by every browser. It's the bridge between HTML markup and JavaScript code: HTML defines the initial tree; JS reshapes it as the user interacts.

The DOM tree

Every HTML document becomes a tree:

<!DOCTYPE html>
<html>
  <head><title>Hello</title></head>
  <body>
    <h1 id="title">Welcome</h1>
    <p class="intro">Hi there!</p>
  </body>
</html>

Becomes a tree like:

document
└── html
    ├── head
    │   └── title
    │       └── "Hello" (text node)
    └── body
        ├── h1#title
        │   └── "Welcome" (text node)
        └── p.intro
            └── "Hi there!" (text node)

Common DOM operations

Selecting elements

document.getElementById('title');
document.querySelector('.intro');
document.querySelectorAll('p');
document.getElementsByClassName('intro');
document.getElementsByTagName('h1');

Reading content

const title = document.getElementById('title');
console.log(title.textContent);  // "Welcome"
console.log(title.innerHTML);    // "Welcome" (HTML)
console.log(title.id);           // "title"

Modifying content

title.textContent = 'Hello, world';
title.innerHTML = '<span>Bold</span>';
title.classList.add('highlighted');
title.setAttribute('data-id', '42');

Creating + inserting elements

const newP = document.createElement('p');
newP.textContent = 'New paragraph';
document.body.appendChild(newP);

// Or insert at specific position
document.body.insertBefore(newP, document.querySelector('.intro'));

Removing elements

const intro = document.querySelector('.intro');
intro.remove();
// Or older API:
intro.parentNode.removeChild(intro);

Event handling

document.getElementById('btn').addEventListener('click', (event) => {
  console.log('Clicked!', event.target);
});

DOM node types

TypeDescription
ElementHTML elements (<div>, <p>, etc.)
TextText content inside elements
CommentHTML comments
DocumentThe root document
DocumentFragmentLightweight container for off-DOM building
AttributeElement attributes

Performance: DOM operations are expensive

DOM manipulation triggers reflow (layout recalculation) and repaint. Slow when overused. Optimization patterns:

  • Batch DOM changes. One reflow per batch, not per change.
  • Use DocumentFragment. Build off-DOM, then insert once.
  • Read then write. Avoid "layout thrashing" (read-write-read-write triggers multiple reflows).
  • Use CSS transforms for animation. No layout impact (vs animating top, left).
  • Virtualize long lists. Render only visible items (react-window, etc.).
  • Debounce/throttle event handlers. Especially scroll, resize.

Virtual DOM (React, Vue) vs real DOM

Frameworks like React maintain a "virtual DOM" — a JS object representation of the real DOM. When state changes:

  1. Compute new virtual DOM
  2. Diff against previous virtual DOM
  3. Apply minimal real DOM changes

This batches and minimizes real DOM operations, often resulting in faster apps. Modern frameworks (Svelte, Solid) skip the virtual DOM entirely and compile to direct DOM updates.

DOM events

Events bubble up from the target element to the document root (default), or capture down (with { capture: true }). Common events:

EventTriggered by
clickMouse click on element
input / changeForm field updates
submitForm submission
keydown / keyupKeyboard interaction
scrollScrolling
resizeWindow resize
load / DOMContentLoadedPage load events
mouseover / mouseoutMouse hover

DOM best practices

  • Cache DOM lookups. Don't document.getElementById in a loop; store the reference.
  • Use event delegation. One listener on parent vs many on children.
  • Prefer textContent over innerHTML. Avoids XSS; faster.
  • Use classes, not inline styles. CSS handles, JS toggles class.
  • requestAnimationFrame for visual updates. Sync with browser paint.
  • Disconnect observers. MutationObserver, IntersectionObserver — clean up.
  • Avoid forced synchronous layout. Read all measurements before any writes.

Common DOM pitfalls

  • innerHTML with user input. XSS vulnerability. Use textContent.
  • Layout thrashing. Reading offsetHeight then writing height in a loop = reflow on every read.
  • Memory leaks. Detached DOM nodes still referenced by JS.
  • Many small DOM updates. Each triggers reflow. Batch with DocumentFragment.
  • Listening on every child. Use event delegation on parent.
  • document.write. Slow + blocks parser. Don't use.
  • Synchronous DOM in scroll handler. Janks scrolling.

FAQ: Document Object Model

Is the DOM the same as HTML?

No. HTML is the source markup. The DOM is the browser's in-memory tree representation, parsed from the HTML. JS interacts with the DOM, not the HTML text.

What's the difference between DOM and BOM?

DOM = the document tree. BOM (Browser Object Model) = the browser itself: window, navigator, history, location.

Why is DOM manipulation slow?

DOM changes trigger reflow + repaint, which the browser must do synchronously. Many small changes = many reflows. Batch them.

Why do React/Vue use a virtual DOM?

To minimize expensive real DOM operations by computing diffs and applying changes in batches.

What's the "Shadow DOM"?

An encapsulated DOM tree attached to an element (used by Web Components). Styles/scripts don't leak in/out.

How do I prevent XSS in DOM operations?

Use textContent instead of innerHTML for user-supplied content. Sanitize HTML if you must use innerHTML (DOMPurify).

What's MutationObserver?

An API to observe DOM changes. Useful for libraries that need to react to dynamic content.

Test DOM-heavy app performance with LoadFocus

LoadFocus runs Lighthouse audits from 25+ regions, measuring main-thread blocking from heavy DOM work and INP. Sign up free at loadfocus.com/signup.

How fast is your website?

Elevate its speed and SEO seamlessly with our Free Speed Test.

Free Website Speed Test

Analyze your website's load speed and improve its performance with our free page speed checker.

×