# DOM manipulation

The Document Object Model (DOM) represents the document (the web page) as a tree of nodes (or objects or elements)

With JavaScript, you can modify (add/remove/change) the entire DOM

node types description
window represents the browser window
document represents the entire document (the root node of the DOM tree)
element node represents an element (an HTML tag)
attribute node the attribute of an element
text node the text inside an element
comment node comments inside an element

DOM

REMARK

The Elements tab inside Chrome's DevTools shows the (modified) DOM (after execution of the scripts), which can differ a lot from the original HTML code (CTRL + U) For example for stubru.be (opens new window), both the original HTML code (only scripts!) and the DOM code are very different ...

# Select elements

Before you can modify the DOM, we first have to select an element on the page The four most commonly used selection methods are:

selector description
document.body (opens new window) select the body element
document.getElementById(<id>) (opens new window) select the element whose id equals <id>
document.querySelectorAll(<CSS selector>) (opens new window) select ALL elements matching <CSS selector>
document.querySelector(<CSS selector>) (opens new window) select THE FIRST element matching <CSS selector>

Open the developer console on this page and use REPL (Read-Eval-Print-Loop) to select some elements

  • document.body
  • document.getElementById('app')
  • document.querySelector('img')
  • document.querySelector('img[alt=DOM]')
  • document.querySelectorAll('h2')

Select items with REPL

# Loop over NodeList

document.getElementById() and document.querySelector() always return one element. On the other hand, document.querySelectorAll() always returns a NodeList, even if there is only one item selected.

A NodeList can be iterated as an array.

In this example:

  1. select all buttons
  2. loop, with the forEach() (opens new window) method, over the NodeList of buttons The first parameter of the callback function inside forEach() represents the element (the button), the second (optional) parameter is the index inside the loop
  3. outputs the information about every button to the console

See the Pen FSLoopNodeList by Jitse Beyens (@BeyensJ) on CodePen.

# Modify content

property description
document.createElement('<element>') (opens new window) create a new element node that you can modify and display
<element>.append(<element>, ...) (opens new window) append specific element(s) to another element
<element>.textContent (opens new window) get or set ALL text inside the <element> (including spaces and hidden text)
<element>.innerText (opens new window) get or set only the VISIBLE text inside the <element> (including spaces but without hidden text)
<element>.innerHTML (opens new window) get or set the HTML content inside <element>

See the Pen FSModifyElements by Jitse Beyens (@jitse-beyens) on CodePen.

# Modify attributes

Every HTML element can have some (default) attributes: e.g. src, title, href, ...

method description
<element>.getAttribute(<attribute>) (opens new window) get the <attribute> of the <element>
<element>.setAttribute(<attribute>, <value>) (opens new window) set the <attribute> of the <element> to <value>
<element>.<attribute> shorthand to get/set the <attribute> of the <element>
<element>.hasAttribute(<attribute>) (opens new window) check if the <attribute> exists on the <element>:
returns true or false
<element>.removeAttribute(<attribute>) (opens new window) remove the <attribute> on the <element>
<element>.attributes get all the attributes on the <element>

See the Pen FSModifyAttributes by Jitse Beyens (@jitse-beyens) on CodePen.

WARNING

Always use <element>.value to get/set the value of an input/form element

<element>.getAttribute('value') returns the initial value of the element's value attribute (even if/after the input element is changed by the user!)

<element>.setAttribute('value', ...) (only) changes the (initial) value attribute of the element (and not the current value of the element)

# The data-* attribute

data-* attributes are a very handy way to add valid, custom attributes to an element (and thus, to store custom data with an element)

The attribute name should not contain any uppercase letters, and must be at least one character long after the data- prefix Examples: data-id, data-photographer, data-unsplash-url, ...

data-* attributes are available via the dataset property:

property example description
<element>.dataset.* (opens new window) get or set the data-* attribute of the <element>
<element>.dataset.photographer use only the suffix after data-
(data-abc <=> <element>.dataset.abc)
<element>.dataset.unsplashUrl if the suffix contains (a) hypen(s), write the suffix in camelCase
(data-abc--opq-xyz <=> <element>.dataset.abcOpqXyz

See the Pen FSDataAttribute by Jitse Beyens (@BeyensJ) on CodePen.

# Modify classes

property description
<element>.className (opens new window) get or replace all the classes on the <element>
<element>.classList (opens new window) get all the classes on the <element>
<element>.classList.add(<c1>, ...) add class(es) to the <element>
<element>.classList.remove(<c1>, ...) remove class(es) from the <element>
<element>.classList.replace(<c1>, <c2>) replace class <c1> by <c2> on the <element>
<element>.classList.toggle(<c>) toggle the class <c> on the <element>:
- add the class if it doesn't exist
- remove the class if it exists
<element>.classList.contains(<c>) check if the class <c> exists on the <element>:
returns true or false

See the Pen FSModifyClasses by Jitse Beyens (@BeyensJ) on CodePen.

Last Updated: 4/23/2024, 6:53:45 PM