Traversing the DOM
Last updated: October 18, 2021.
In a previous article, we covered how to select DOM elements, i.e. select elements by ID or class using the getElementById
, getElementsByClassName
, getElementsByTagName
, querySelector
and querySelectorAll
methods.
In this article, we cover a related topic: how to reach nearby nodes and elements of an already selected element.
Why traverse the DOM?
In some situations, it is better to traverse than to repeatedly select elements.
For example, when programming a blog, a new post could be programmed to appear as the ‘first child’ of a container div. Or, when programming a ‘clear cart’ button for a webshop, it is easier to delete all the ‘children’ (items) from the cart (its ‘parent’ element) than to program the selection of each item individually.
Learning how to traverse the DOM efficiently will make it much easier for you to manipulate it.
HTML template for this tutorial
To follow along with this tutorial, save this code in a new HTML document and create a new script.js
file in the same directory.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> div { margin-left: 5vw; } </style> </head> <body> <div id="grandparent"> Grandparent <div id = "parent1"> Parent 1 <div id = "p1child1">Child 1</div> <div id = "p1child2">Child 2</div> <div id = "p1child3">Child 3</div> </div> <div id = "parent2"> Parent 2 <div id = "p2child1">Child 1</div> <div id = "p2child2">Child 2</div> <div id = "p2child3">Child 3</div> </div> </div> <script src="script.js"></script> </body> </html>
This should render something like the following to your screen:

How to traverse the DOM
We can actually traverse the DOM without selecting any elements at all first.
We can do this by calling the document
object and applying to it either the head
or body
method:
console.log(document.head) // Returns the head section of the DOM console.log(document.body) // Returns the body section of the DOM
This is useful in some contexts. But often we want to select nearby nodes or elements of a select element.
Traversing down
As a starting point, let’s select the grandparent
div:
const grandparent = document.getElementById('grandparent');
From here, let’s try to select the ‘first child’ of this element by using the firstChild
method:
console.log(grandparent.firstChild) // Result: “ Grandparent “
You may have expected this to return the parent1 div, but instead it returns the text “ Grandparent “. This is because this text is in fact the first child of grandparent. To select the first element, we must specify this explicitly using the firstElementChild
method:
console.log(grandparent.firstElementChild) // Selects parent1 div
Similarly, we select the ‘last child’:
console.log(grandparent.lastChild) // Returns text “ “ console.log(grandparent.lastElementChild) // Returns parent2 div
You might be wondering why grandparent.lastChild
returns an empty text object. This is because the ‘last child’ of the grandparent
div is the empty character space between the closing div tag of parent2
and grandparent
. Again, we need to use lastElementChild
if we want to select the last element.
If we want to select all the children of the grandparent element, we can apply the children
method. And we can add the index of a child inside square brackets to select a specific child from the children of grandparent
.
console.log(grandparent.children) // Returns parent1 and parent2 div console.log(grandparent.children[0]) // Returns parent1 div console.log(grandparent.children[1]) // Returns parent2 div
Unlike firstChild
and lastChild
, the children method selects elements only.
To go down multiple levels, the downwards traversal methods can be combined. For example:
console.log(grandparent.firstElementChild.lastElementChild) // Returns the p1child3 div
Traversing up
For traversing up, let’s start by selecting one of the lowest level elements:
const p1child2 = document.getElementById('p1child2')
To traverse upwards from this starting point, the parentNode
or parentElement
method can be used:
console.log(p1child2.parentNode) // Returns parent1 div console.log(p1child2.parentElement) // Returns parent1 div
Both parentNode
and parentElement
return the same result because an element is a type of node. In practice, the parent of an element or node is almost always an element. So both usually return the same result.
parentNode
and parentElement
methods. For example, calling console.log(document.documentElement.parentElement)
returns null
whereas console.log(document.documentElement.parentNode)
returns the document object node. This is because there is no parent element of document.documentElement
.
However, this is a contrived example. In the vast majority of use cases, both return the same result.
To traverse up, the methods can be combined:
console.log(p1child2.parentElement.parentElement) // Returns grandparent div
Traversing horizontally
Continuing from the selected p1child2
element, we can travsere sideways by using the nextSibling
and previousSibling
methods:
console.log(p1child2.nextSibling) // Returns empty text object console.log(p1child2.previousSibling) // Returns empty text object
You may have expected this to select the p1child3
and then the p1child1
div. But because elements have not been selected explicitly, the empty text space between p1child2
div and the other divs is selected.
To select the sibling elements, we must specify this using nextElementSibling
and previousElementSibling
:
console.log(p1child2.nextElementSibling) // Returns p1child3 div console.log(p1child2.previousElementSibling) // Returns p1child1 div
Summary
Traversal direction | Method | Selects |
---|---|---|
Traversing down | .firstChild | First child |
.firstElementChild | First child element | |
.lastChild | Last child | |
.lastElementChild | Last child element | |
.children | All child elements | |
.children[0] | Child element index 0 | |
Traversing up | .parentNode | Parent node |
.parentElement | Parent element | |
Traversing horizontally | .nextSibling | Next node or element |
.previousSibling | Previous node or element | |
.nextElementSibling | Next element | |
.previousElementSibling | Previous element |