The Document Object Model
When a browser loads an HTML page, it creates a tree-structured representation called the Document Object Model. Each HTML element becomes a node in this tree, and so does each piece of text and each comment. JavaScript can access and modify this tree through the global document object.
From HTML to DOM
Here is a simple HTML page:
<!DOCTYPE html>
<html>
<head>
<title>My Page</title>
</head>
<body>
<h1>Hello</h1>
<p>Welcome to my page.</p>
</body>
</html>
The browser constructs a tree where the document is the root, with html as its child. The html element has two children: head and body. Each of those has its own children.
The document and window Objects
In the browser, there are two global objects you will use all the time:
// window is the global object in browsers
console.log(window.innerWidth); // Browser window width
console.log(window.location); // Current URL information
// document represents the HTML document
console.log(document.title); // Page title
console.log(document.body); // The <body> element
The window object represents the browser window and provides properties like dimensions and location. The document object represents the loaded HTML and provides methods to access and modify elements.
Node Types
The DOM contains different types of nodes, but you will primarily work with element nodes (HTML tags like <div>, <p>, <span>). Text content and comments are also nodes, which is why some navigation properties distinguish between “all nodes” and “element children only.”
Navigating the DOM Tree
Every node in the DOM has properties that reference related nodes:
const container = document.querySelector(".container");
// Parent relationship
console.log(container.parentNode); // Parent node (any type)
console.log(container.parentElement); // Parent element specifically
// Child relationships
console.log(container.childNodes); // All child nodes (NodeList)
console.log(container.children); // Only element children (HTMLCollection)
console.log(container.firstChild); // First child node (any type)
console.log(container.firstElementChild); // First child element
console.log(container.lastChild); // Last child node
console.log(container.lastElementChild); // Last child element
// Sibling relationships
console.log(container.nextSibling); // Next sibling node
console.log(container.nextElementSibling); // Next sibling element
console.log(container.previousSibling); // Previous sibling node
console.log(container.previousElementSibling); // Previous sibling element
The distinction between childNodes/firstChild and children/firstElementChild matters because text nodes (including whitespace between elements) are nodes too:
<div id="parent">
<span>First</span>
<span>Second</span>
</div>
const parent = document.querySelector("#parent");
// childNodes includes text nodes (whitespace)
console.log(parent.childNodes.length); // 5 (text, span, text, span, text)
// children includes only elements
console.log(parent.children.length); // 2 (span, span)
The DOM is Live
The DOM tree is a live representation of the page. Changes you make through JavaScript immediately affect what the user sees, and changes to the page (like form input) are reflected in the DOM:
// Changes to DOM immediately appear on screen
document.body.style.backgroundColor = "lightblue";
// User input is reflected in DOM
const input = document.querySelector("input");
// After user types "hello"
console.log(input.value); // "hello"