Learn JavaScript DOM Traversal
Introduction
When a web page gets loaded in the browser, the DOM or Document Object Model gets created.
This Document Object Model is a tree-like structure representing the arrangement or hierarchy of elements on a page.
We often want to navigate or traverse that structure with JavaScript because this allows us to manipulate page elements in various ways.
The DOM Tree Hierarchy
The DOM tree is structured as a hierarchy. (Think of a family tree of grandparent to parent to child or siblings).
For example, within a pair of body tags, we have a div with an id of grandparent. Within that grandparent div, we have another div with an id of parent. And finally, within that parent div, we have a div with an id of child.
<body>
<div class="box" id="grandparent">
<div class="box" id="parent">
<div class="box" id="child"></div>
</div>
</div>
</body>
Getting Reference to a DOM Element
Traversing and manipulating the DOM requires getting a reference to a DOM element first.
We'll use querySelector to get a reference to the div with id of parent..
const parentDiv = document.querySelector("#parent");
Now that we have a reference into the DOM, we can begin traversing it.
And there are three different directions we can travel:
- up the DOM tree
- down the DOM tree
- sideways (to visit a neighboring sibling element)
Traversing Up
To traverse up the DOM tree, let's take that parentDiv and use a property called parentElement.
If we examine it in the console, we can see we're getting the div with an id of grandparent. This grandparent div is the parent of the div with an id of parent.
const parentDiv = document.querySelector("#parent");
console.dir(parentDiv.parentElement);
Traversing Down
To traverse down the DOM tree, let's take the parentDiv element again but use the children property this time. The children property will give us an HTML Collection. This HTML Collection contains the child elements of the parent div.
const parentDiv = document.querySelector("#parent");
console.dir(parentDiv.children);
In the console, we get one element: the div with an id of child.
If we duplicate that child div, we can now see two child elements in the console.
<div class="box" id="grandparent">
<div class="box" id="parent">
<div class="box" id="child"></div>
<div class="box" id="child"></div>
</div>
</div>
We can use square brackets to access a specific element. To get the second
child div, for example, we'd enclose the number 1 in square brackets.
const parentDiv = document.querySelector("#parent");
console.dir(parentDiv.children[1]);
Traversing Sideways
Now, let's try traversing sideways to visit a sibling element. Those divs with the id of child are siblings since they exist on the same level.
<div class="box" id="grandparent">
<div class="box" id="parent">
<div class="box" id="child"></div>
<div class="box" id="child"></div>
</div>
</div>
Previously, we used parentDiv.children[1] to access the second child div.
const parentDiv = document.querySelector("#parent");
console.dir(parentDiv.children[1]);
So, from that point, to access the first child div, we can use the previousElementSibling property.
const parentDiv = document.querySelector("#parent");
console.dir(parentDiv.children[1].previousElementSibling);
If we had been on the first child div, we could use nextElementSibling to get the second one.
const parentDiv = document.querySelector("#parent");
console.dir(parentDiv.children[0].nextElementSibling);
Nodes vs. Elements
Now, when we traverse the DOM, we sometimes traverse by element and sometimes by node.
You see, there's a difference between a DOM node and a DOM element.
While all HTML elements are nodes, not all nodes are HTML elements.
To illustrate this point, let's create a comment under our grandparent div. This comment is a specific type of node called a comment node.
<div class="box" id="grandparent">
<!-- My Comment -->
<div class="box" id="parent">
<div class="box" id="child"></div>
<div class="box" id="child"></div>
</div>
</div>
We can also create another type of node called a text node. In this example, the text node consists of the words "The Code Creative" after the first child div.
<div class="box" id="grandparent">
<!-- My Comment -->
<div class="box" id="parent">
<div class="box" id="child"></div>
The Code Creative
<div class="box" id="child"></div>
</div>
</div>
Believe it or not, even white space, line breaks, and carriage returns classify as text nodes.
Our divs are nodes as well. These are specifically called element nodes.
For your reference, here are the various node types listed on MDN.
Element Properties and Node Properties
This chart shows the element properties and their corresponding node properties.
To get a parent node, for example, we could use parentNode instead of parentElement. Instead of children, we could use childNodes. And we can use nextSibling and previousSibling in place of nextElementSibling and previousElementSibling.
Let's try an example where we access nodes rather than HTML elements.
Rather than using parentDiv.children, we'll use parentDiv.childnodes.
const parentDiv = document.querySelector("#parent");
console.dir(parentDiv.childNodes);
In the console, we see a node list with five elements.
Not only are we getting the two child divs within that parent div but we're also getting three text nodes. Those text nodes are the line breaks that occur after each element.
If you're more of a visual learner, check out the video version of this article: