What Is the DOM? Document Object Model Explained
The DOM is the browser's in-memory tree of a web page. Learn how it is built, how JavaScript changes it and how DOM size affects speed.
What is the DOM?
The Document Object Model (DOM) is the browser's in-memory representation of a web page. When the browser parses HTML, it builds a tree of nodes (elements, text and attributes), and scripts use the DOM API to read and change that tree's structure, style and content. The DOM is a Web API, not part of the JavaScript language itself, according to MDN.
How the browser builds the DOM
The browser turns HTML bytes into characters, then tokens, then objects, and links the objects into a tree that mirrors the parent-child relationships in the markup. It does the same for CSS, building a separate tree called the CSSOM. The two are independent structures that the browser combines to decide what to paint, which is why a page cannot render before its CSS is known. The DOM is not a literal copy of your source: it keeps whitespace as text nodes, and scripts can add, move or remove nodes after the page loads, so the DOM you inspect in DevTools can differ from "view source".
Nodes, elements and the API
Every object in the tree is a node. An element is the most common kind, but text and attributes are nodes too. The document object is the root you start from. Take this markup:
<body>
<h1>Pricing</h1>
<p class="note">Billed monthly</p>
</body>Three lines of JavaScript select, change and react to it:
const note = document.querySelector(".note"); // select the first matching element
note.textContent = "Billed yearly"; // change its text
note.addEventListener("click", () => note.remove()); // react to a click, then remove itRendering approaches differ mainly in where the DOM gets built. In a single-page app most of it is created by JavaScript in the browser. With server rendering, the server sends HTML and the browser builds the DOM from it, then hydration attaches the event handlers.
When is the DOM ready?
DOMContentLoaded fires once the HTML is fully parsed and the deferred scripts have run. It does not wait for images, subframes or async scripts, and the later load event marks the fully loaded page. MDN notes that using load where DOMContentLoaded would do is a common mistake. Scripts that need elements to exist should use defer or wait for DOMContentLoaded, or check document.readyState first.
The DOM and page speed
Every change to the DOM can trigger style, layout and paint work, and the cost grows with the size of the tree. Lighthouse warns when the body has more than about 800 nodes and flags an error above about 1,400. Large trees slow style recalculation and layout, and broad selectors such as querySelectorAll("li") can hold thousands of node references in memory. That shows up in responsiveness, and so in Interaction to Next Paint (INP). Late-inserted elements without reserved space also push content around and hurt Cumulative Layout Shift.
Common mistakes
- Writing user input with
innerHTML. MDN calls it probably the most common vector for cross-site scripting. UsetextContentfor plain text. - Layout thrashing. Alternating DOM reads such as
offsetWidthwith style writes in a loop forces the browser to recalculate layout on every pass. Batch the reads first, then do the writes. - Querying too early. A script in
<head>withoutdeferruns before the body exists, soquerySelectorreturnsnull. - Deep, wrapper-heavy markup. Flatten nesting and use flexbox or grid instead of extra container elements.
- Rendering everything up front. Long lists and hidden sections add nodes nobody sees yet. Load them lazily or use
content-visibility.
The DOM in testing and monitoring
A protocol-level load test, such as one run with JMeter, sends HTTP requests and never builds a DOM, so it cannot tell you how heavy a page is for the browser. For that you need a real browser. LoadFocus Core Web Vitals Checker shows field data for a URL, including responsiveness, and Page Speed Monitoring runs scheduled Lighthouse audits from 25 cloud regions (Lighthouse is the tool behind the DOM size warning above). For INP fixes, read how to optimize Interaction to Next Paint, and to set up alerts, how to monitor Core Web Vitals.
FAQ: Document Object Model
Is the DOM part of JavaScript?
No. The DOM is a Web API that browsers provide. JavaScript is the most common language used to call it, but the DOM is defined separately.
What is the difference between the DOM and the HTML source?
The source is the text your server sends. The DOM is the live tree the browser builds from it. Scripts can change the DOM after load, so DevTools may show nodes that are not in "view source".
How many DOM nodes is too many?
Lighthouse warns at about 800 nodes in the body and reports an error at about 1,400. Those are guideline thresholds, not hard limits, and a page can be slow below them if its selectors and layout are expensive.
What is the difference between DOMContentLoaded and load?
DOMContentLoaded fires when the HTML is parsed and deferred scripts have run, without waiting for images or async scripts. The load event fires later, when the page is fully loaded.
Why is innerHTML risky?
It parses a string as HTML, so unsanitized user input can run malicious JavaScript through attributes such as onerror. Use textContent when the content is plain text.
Does DOM size affect Core Web Vitals?
It can. Expensive style and layout work caused by a large DOM slows interactions, which counts against INP, and late-inserted elements can shift the layout.
Related terms
- First Contentful Paint (FCP): Definition, Thresholds, Fixes
- First Input Delay (FID): Definition and Replacement by INP
- Image Size: Definition, Web Optimization, Best Practices
- What is Infrastructure Monitoring?
- Interaction to Next Paint (INP): Definition, Thresholds, Fixes
- What is JMeter?
- Largest Contentful Paint (LCP): Definition, Thresholds, Fixes
- What is Latency?
Related LoadFocus Tools
Put this concept into practice with LoadFocus, the same platform that powers everything you just read about.