← Back to JavaScript Course | Chapter 4: Modern JS, Async & DOM | Lesson 21 of 26

JS DOM Navigation

Once you have selected one DOM element, you often need to move to a nearby one -- its parent, its next sibling, its first child -- without running a whole new query. DOM navigation properties (parentNode, nextElementSibling, firstElementChild, and more) let you walk the tree relative to an element you already have.

Navigating to a Parent Element

.parentElement returns an element's direct parent in the DOM tree -- useful for walking upward, like finding the containing card or list item of a button that was clicked, without needing to have selected that ancestor directly.

Note: Use .parentElement (which returns an Element or null) rather than the older .parentNode when you specifically want an Element result, not any node type.

Warning: Calling .parentElement on the root <html> element returns null, since it has no parent element -- code walking upward repeatedly should account for eventually hitting that boundary.

Example: Navigating to a Parent Element

javascript
<div id="parent"><button id="child">Click</button></div>
<script>
  const child = document.getElementById("child");
  console.log(child.parentElement.id);
</script>

Navigating to Child Elements

.children returns a live collection of an element's direct child elements (excluding text and comment nodes), and .firstElementChild / .lastElementChild jump directly to the first or last of those children, without needing to index into the full collection.

Note: Use .children instead of .childNodes when you specifically want only element children, skipping whitespace text nodes that often sit between tags in formatted HTML.

Warning: .firstElementChild and .lastElementChild return null if the element has no child elements at all, even if it contains text content.

Example: Navigating to Child Elements

javascript
<ul id="list"><li>A</li><li>B</li></ul>
<script>
  const list = document.getElementById("list");
  console.log(list.children.length);
  console.log(list.firstElementChild.textContent);
  console.log(list.lastElementChild.textContent);
</script>

Navigating to Sibling Elements

.nextElementSibling and .previousElementSibling move to the adjacent element at the same tree level, in either direction -- useful for relative operations, like highlighting the item right after the one a user clicked.

Note: Use these sibling properties when an operation genuinely depends on tree position relative to a known element, rather than re-querying the whole document.

Warning: The first element in a group has no previousElementSibling (returns null), and the last has no nextElementSibling (also null) -- always guard against this at the boundaries.

Example: Navigating to Sibling Elements

javascript
<ul><li id="first">A</li><li id="second">B</li></ul>
<script>
  const first = document.getElementById("first");
  console.log(first.nextElementSibling.textContent);
</script>

Navigating Relative to an Event Target

Combining event.target (the element that triggered an event) with navigation properties lets you find and manipulate related elements without needing separate IDs for everything -- like finding a delete button's containing list item to remove it, working purely from tree relationships.

Note: Use relative navigation from event.target for components with repeated structure (like list items), avoiding the need to assign unique IDs to every single related element.

Warning: Navigating from event.target assumes a specific, consistent tree structure -- if the HTML structure changes later, navigation code written around it can silently break.

Example: Navigating Relative to an Event Target

javascript
<ul>
  <li>Item <button class="del">X</button></li>
</ul>
<script>
  document.querySelector(".del").addEventListener("click", (e) => {
    console.log(e.target.parentElement.textContent);
  });
</script>

Navigation vs Re-querying: Which to Use

Navigation properties are ideal when you already have a reference to a nearby element and just need to move relative to it -- re-running querySelector() from the document root makes more sense when you need to find something unrelated to any element you currently hold a reference to.

Note: Reach for a navigation property when the target element's position relative to one you already have is known and stable; use querySelector for anything else.

Warning: Chaining many navigation properties together (parentElement.parentElement.nextElementSibling.firstElementChild) to reach a distant element makes code fragile and hard to read -- a targeted selector is often clearer.

Example: Navigation vs Re-querying: Which to Use

javascript
<div id="card"><button id="btn">Click</button></div>
<script>
  document.getElementById("btn").parentElement;
  console.log(document.querySelector("#card"));
</script>
Common Mistakes
  1. Using the non-Element-specific properties (childNodes, nextSibling) when you specifically want element-only navigation, since those include text nodes (like whitespace) that childNodes and nextSibling do not filter out.
  2. Assuming a navigation property always returns something -- .nextElementSibling on the last child, or .parentElement on the document root, returns null, and code needs to handle that.
  3. Re-querying the DOM with querySelector when a simple navigation property (like .parentElement) would find the same element with less overhead.
Chapter Summary
  • parentElement, children, firstElementChild, and lastElementChild navigate to related elements, skipping over text/comment nodes.
  • nextElementSibling and previousElementSibling move to adjacent sibling elements at the same tree level.
  • These properties can return null when there is nothing in that direction, so checking before using the result matters.
Browser Support

All Element-based DOM navigation properties are supported in every modern browser.

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.