The rendering pipeline

The Document Object Model (DOM)

Learn what the DOM (Document Object Model) is: the browser's representation of a page as nodes, and how to traverse and edit it with window and document.

The Document Object Model, or DOM, is the browser’s representation of an HTML document as a tree of objects in memory. JavaScript uses this tree to inspect and change the page.

When the browser parses HTML, it creates a node for the document, for every element, every piece of text, and every comment. Frameworks update the page through this tree too, and you can inspect it live with the Browser Developer Tools.

The DOM is not part of the JavaScript language. It’s a Web API the browser gives to JavaScript.

The DOM is standardized by WHATWG in the DOM Living Standard Spec.

The two objects you’ll use most are window and document.

The Window object

window represents the browser window that contains the document. It’s also the global object, so window.document is usually written just document.

Properties you’ll reach for a lot:

  • console: the debugging console, console.log and friends
  • document: the entry point to the DOM
  • history: the History API
  • location: the Location interface, with the URL, protocol, hash and more
  • localStorage and sessionStorage: the Web Storage API

And methods:

  • alert(): shows an alert dialog
  • postMessage(): sends messages between windows
  • requestAnimationFrame(): runs a callback before the next paint
  • setInterval() and clearInterval(): run a function every n milliseconds until cleared
  • setTimeout(): run a function after n milliseconds
  • addEventListener() and removeEventListener(): listen for events on the window

The full reference is at https://developer.mozilla.org/en-US/docs/Web/API/Window.

The Document object

document represents the DOM tree loaded in the window. Here’s how the head and body tags look in the tree:

DOM, the body and head tags

A head containing a title with its text:

DOM, the head tag with the title

A body containing a link, with its text and its href attribute:

DOM, the body tag with a link

The methods you’ll use most are the Selectors API:

  • document.getElementById()
  • document.querySelector()
  • document.querySelectorAll()
  • document.getElementsByTagName()
  • document.getElementsByClassName()

You can read the title with document.title, the URL with document.URL, the referrer with document.referrer, the cookies with document.cookie, and the last modified date with document.lastModified.

Three properties give you the main Element nodes directly: document.documentElement (the root html element), document.body and document.head.

The DOM nodes

document.links, document.images and document.forms return an HTMLCollection of all the links, images and forms in the page.

Avoid document.write(). It can replace the whole document and hurts performance. Use the editing methods below instead.

The full reference is at https://developer.mozilla.org/en-US/docs/Web/API/Document.

Types of nodes

The node types you’ll meet most often:

  • Document: the root of the tree
  • Element: an HTML tag
  • Attr: an attribute, a node that isn’t stored as a child in the tree
  • Text: text inside an element
  • Comment: an HTML comment
  • DocumentType: the Doctype declaration

Traversing the DOM

From any node you can move to its parent, its children, and its siblings.

Getting the parent

Every element has just one parent. Get it with parentNode or parentElement. parentNode returns any kind of node, parentElement returns an Element or null. Use parentElement when you need an element.

Getting the children

node.hasChildNodes() tells you if there are any. node.childNodes returns all of them, text and comments included.

element.children returns only the child elements, skipping whitespace text nodes. That’s the one you want most of the time. The MDN DOM anatomy guide shows why.

Get the children of a node

element.firstElementChild and element.lastElementChild give you the first and last child element:

To get the first or last child Element Node

node.firstChild and node.lastChild don’t filter, so they often return a whitespace Text node.

Getting the siblings

Use element.previousElementSibling and element.nextElementSibling. The unfiltered previousSibling and nextSibling include whitespace text nodes, so I avoid them.

Editing the DOM

Create nodes with document.createElement() and document.createTextNode(), then attach them with appendChild():

const div = document.createElement('div')
div.appendChild(document.createTextNode('Hello world!'))
document.body.appendChild(div)

The other methods you’ll need:

  • parent.removeChild(child) removes a child
  • parent.insertBefore(newNode, existingNode) inserts before another child
  • element.appendChild(newChild) adds after the existing children
  • element.prepend(newChild) adds before the existing children
  • element.replaceChild(newChild, existingChild) swaps a child
  • element.insertAdjacentElement(position, newElement) inserts at a given position
  • element.textContent = 'Hello' replaces the text content

Lesson completed