JavaScript: DOM Manipulation

Select, modify, create, remove, and traverse HTML elements using the browser's Document Object Model API.

What is the DOM?

The DOM (Document Object Model) is a live, tree-structured representation of an HTML page that the browser creates when it loads the document. JavaScript uses the DOM API to read and change elements, attributes, styles, and content without reloading the page.

Document Object Model

A programming interface that represents the page as a tree of nodes JavaScript can read and manipulate.

  • Every HTML tag becomes a node in the tree
  • The root of the tree is document
  • Changes to DOM nodes are reflected instantly in the browser
  • The DOM is not the HTML source: it is a live object graph built from it

The document Object

document is the root of the DOM tree: everything on the page is reachable from it.

DOM Tree Structure

The browser parses HTML into a tree of nodes. Element nodes represent tags, text nodes hold visible text, and attribute nodes store tag attributes. Understanding the tree is essential for traversal and targeting the right element.

Node Types

The DOM tree is made of different node types: element nodes are the most commonly manipulated.

  • Element node: represents an HTML tag, e.g. <div>, <p>
  • Text node: the text content inside an element
  • Document node: the root document object
  • Every node has a nodeType property: 1 for elements, 3 for text, 9 for document

DOM Tree Example

Each tag is an element node. Text inside is a text node child.

Selecting Elements

Before modifying the DOM you must select the element. The modern standard is querySelector and querySelectorAll: they accept any CSS selector. The older methods (getElementById etc.) are still widely seen.

Selection Methods

querySelector and querySelectorAll cover every use case with familiar CSS selector syntax.

  • getElementById("id"): returns one element or null
  • getElementsByClassName("cls"): live HTMLCollection
  • getElementsByTagName("tag"): live HTMLCollection
  • querySelector(".cls"): first match or null (static)
  • querySelectorAll(".cls"): static NodeList of all matches

Selecting Elements

Try all five selection methods against this HTML.

innerHTML, textContent, innerText

These three properties read or set the content of an element. They differ in how they handle HTML tags and whitespace: choosing the wrong one can introduce XSS vulnerabilities or unexpected formatting.

Content Properties

Use textContent for plain text. Only use innerHTML when you intend to insert real HTML markup.

  • innerHTML: parses the string as HTML: risky with user input (XSS)
  • textContent: treats content as plain text, ignores tags: safe and fast
  • innerText: like textContent but respects CSS visibility and formatting
  • Never set innerHTML from untrusted user input without sanitising first

innerHTML vs textContent

Watch how each property handles the same tag string differently.

setAttribute() and getAttribute()

Attributes live on the HTML tag itself. getAttribute reads them as strings. setAttribute writes them. removeAttribute deletes them entirely.

Attributes vs Properties

Attributes are the HTML source values. Properties are the live JS object values. They can differ.

  • getAttribute("href"): returns the literal string from the HTML
  • setAttribute("class", "active"): sets the attribute on the element
  • removeAttribute("disabled"): removes the attribute completely
  • hasAttribute("hidden"): returns boolean

setAttribute and getAttribute

Read, update, and remove attributes on these two elements.

style Property

Every element has a style object for reading and writing inline CSS. Properties are camelCase in JavaScript (backgroundColor not background-color). Prefer toggling CSS classes over writing inline styles directly.

element.style

Direct style manipulation works but class toggling is cleaner and easier to maintain.

  • CSS properties are camelCase: fontSize, backgroundColor, borderRadius
  • element.style.color = "red" writes an inline style
  • To read computed styles (from stylesheets): use getComputedStyle(el)
  • Prefer classList.add("highlight") over setting styles directly

Direct Style Manipulation

Click the button to toggle inline styles on the paragraph.

classList

The classList API is the standard way to manage CSS classes. It provides add, remove, toggle, and contains: all more reliable than manipulating className as a string.

classList Methods

classList is the preferred way to control classes: it never accidentally removes other classes.

  • classList.add("cls"): adds the class
  • classList.remove("cls"): removes the class
  • classList.toggle("cls"): adds if absent, removes if present
  • classList.contains("cls"): returns boolean
  • classList.replace("old", "new"): swaps one class for another

classList in Action

Click the button to toggle the active class on the paragraph.

createElement(), appendChild(), append()

To add new content dynamically, create an element with document.createElement(), configure it, then insert it into the DOM. append() is the modern method and accepts both nodes and strings.

Creating and Inserting Elements

Create, configure, then insert. The element only appears in the page after insertion.

  • document.createElement("div"): creates a detached element
  • parent.appendChild(el): inserts as the last child (accepts Node only)
  • parent.append(el, "text"): modern: accepts Nodes and strings, adds multiple
  • parent.prepend(el): inserts as the first child

createElement and append

Each click creates a new li and appends it to the list.

removeChild() and remove()

Elements can be removed from the DOM with element.remove() (modern) or parent.removeChild(child) (older). Removal takes the element out of the document: it is not destroyed if you hold a reference to it.

Removing Elements

remove() is the modern, self-contained method. removeChild() requires a reference to the parent.

  • el.remove(): removes itself from the DOM (ES2015+)
  • parent.removeChild(child): older approach, returns the removed node
  • The removed element still exists in memory if a JS variable holds it
  • Re-inserting a removed element is valid: just append it somewhere again

Removing Elements

Click X on any item to remove it from the list.

insertBefore(), insertAdjacentHTML(), cloneNode()

For precise insertion control, insertBefore places a node before a reference child. insertAdjacentHTML inserts raw HTML at four named positions around an element. cloneNode duplicates an element.

Precise Insertion and Cloning

insertAdjacentHTML is the most flexible insertion method: four positions around any element.

  • parent.insertBefore(newEl, refEl): inserts newEl before refEl
  • el.insertAdjacentHTML("beforebegin"): before the element itself
  • el.insertAdjacentHTML("afterbegin"): inside, before first child
  • el.insertAdjacentHTML("beforeend"): inside, after last child
  • el.insertAdjacentHTML("afterend"): after the element itself
  • el.cloneNode(true): deep clone including all descendants

insertBefore and cloneNode

Inserts a First item before Second, then cloning adds duplicates.

Traversing the DOM

DOM traversal properties let you navigate the tree relative to a known element: without querying by selector. This is useful for event delegation and working with adjacent sibling elements.

Traversal Properties

Navigate up, down, and sideways in the tree from any element.

  • el.parentElement: the direct parent element
  • el.children: live HTMLCollection of child elements (no text nodes)
  • el.firstElementChild / lastElementChild: first and last child elements
  • el.nextElementSibling / previousElementSibling: adjacent siblings
  • All return null when the position does not exist

DOM Traversal

Navigate the list structure using traversal properties.

Knowledge Check

1. What does the DOM represent?

2. What does querySelector() return when no match is found?

3. What is the difference between textContent and innerHTML?

4. Which classList method checks if a class is present on an element?

5. What is the difference between append() and appendChild()?

6. What does cloneNode(true) do?

7. What does parentElement return for the root <html> element?

8. Which method returns a live HTMLCollection that updates automatically?