DOM Introduction
The Document Object Model — usually just "the DOM" — is the bridge between the HTML you write and the JavaScript that runs on the page. When a browser loads an HTML document, it does not keep it as a string. It parses the markup into a tree of objects that your code can read, modify, and listen to. Everything we'll do in the next several pages — selecting elements, changing text, reacting to clicks — happens through that tree.
What the DOM actually is
The DOM is a living, in-memory representation of the page. It is not the HTML file on disk, and it is not what View Source shows you. It is the structure your browser is currently rendering, complete with any changes JavaScript has already made.
It is a tree — a single root node (
document) with nested children.It is live — when JavaScript mutates a node, the screen updates.
It is language-agnostic — the DOM is a W3C/WHATWG standard, but in practice we always access it from JavaScript.
It is provided by the browser, not by the JavaScript engine. Node.js has no DOM by default.
From HTML text to a tree
Consider a tiny page:
page.html
<!DOCTYPE html>
<html lang="en">
<head>
<title>Hello DOM</title>
</head>
<body>
<h1 id="title">Hello</h1>
<p class="lead">Welcome to the DOM.</p>
</body>
</html>When the browser parses that file, it builds a tree that conceptually looks like this:
DOM tree (sketch)
document
└── html
├── head
│ └── title -> "Hello DOM"
└── body
├── h1#title -> "Hello"
└── p.lead -> "Welcome to the DOM."Each box in that diagram is a node. Nodes have parents, children, siblings, and properties you can inspect from JavaScript.
The kinds of nodes
Not everything in the DOM is an element. The spec defines several node types; in day-to-day work you mostly care about three:
Element nodes — tags like
<h1>,<p>,<div>. These are what you almost always select and manipulate.Text nodes — the actual text inside an element. The string
"Hello"inside<h1>is a separate text-node child of that<h1>.Comment nodes — HTML comments (
<!-- like this -->). They appear in the tree but render as nothing.
There are others (document, doctype, document fragment), but those three cover 95% of real code. Every node has a numeric nodeType and a string nodeName you can inspect.
inspecting node types
const h1 = document.getElementById("title");
h1.nodeType; // 1 (Node.ELEMENT_NODE)
h1.nodeName; // "H1"
h1.firstChild.nodeType; // 3 (Node.TEXT_NODE) — the "Hello" text
h1.firstChild.nodeValue; // "Hello"How the browser builds the DOM
The path from a URL to a fully rendered page is more interesting than it looks. At a high level:
Fetch — the browser downloads the HTML bytes.
Tokenise & parse — bytes become characters become tokens become a tree of nodes. As nodes are created they are attached to
document.CSSOM — stylesheets are parsed into a parallel tree of style rules.
Scripts run —
<script>tags execute as the parser reaches them (unless they havedeferorasync), and their JavaScript can already see and modify the DOM that has been built so far.Layout & paint — the browser combines the DOM and CSSOM, computes positions, and paints pixels.
That is why you'll see advice like "put your <script> tags at the bottom of <body>" or "use defer": by the time the script runs, the elements it wants to touch already exist in the tree.
The DOM is not your HTML file
This is the most common point of confusion. The HTML on disk is just the initial recipe. Once the browser parses it and your JavaScript runs, the DOM can drift away from that file in three ways:
The parser may insert missing tags (
<tbody>inside a<table>, a<head>, a<body>) to repair malformed markup.JavaScript can add, remove, or rewrite elements at any time after the page loads.
Devtools is showing you the current DOM, not the source. "View source" shows the original bytes; "Inspect" shows the live tree.
document is the entry point
Every DOM operation starts from the global document object. A handful of properties are worth memorising:
document shortcuts
document.documentElement; // the <html> element document.head; // the <head> element document.body; // the <body> element document.title; // the document title (you can assign to it!) document.URL; // the current URL as a string document.readyState; // "loading" | "interactive" | "complete"
We'll spend the next few pages building on these — first finding the elements you want, then walking around the tree, then changing what's inside.
Where the DOM lives
In the browser, the DOM is a native API the engine wraps in JavaScript objects.
In Node.js there is no DOM —
documentis undefined. Libraries likejsdomemulate it for testing.In server-side rendering (Next.js, Astro, etc.) the framework renders HTML to a string on the server; the browser still builds the real DOM when that HTML arrives.
Keep that in mind: code that touches document runs in the browser only. In a framework like Next.js you mark such code with "use client" or guard it with typeof window !== "undefined".