JavaScriptDOM Introduction

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

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)

JS
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

JS
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 have defer or async), 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.

A useful mental model
Think of the HTML file as the *blueprint* and the DOM as the *building*. The building starts identical to the blueprint, but it can be remodelled at runtime — and the browser only paints what is actually in the building.
document is the entry point

Every DOM operation starts from the global document object. A handful of properties are worth memorising:

document shortcuts

JS
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 — document is undefined. Libraries like jsdom emulate 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".