JavaScript Notes
Master DOM traversal in JavaScript. Learn parentNode, children, firstElementChild, nextElementSibling, closest(), and more to navigate the DOM tree efficiently with real examples.
What is DOM Traversal?
Once you have a reference to one element, you often need to move to related elements — its parent, siblings, or children — without calling querySelector again. This is called DOM traversal.
Think of the DOM tree like a family tree: every node has a parent (except the root), can have children, and has siblings at the same level.
DOM Parent-Child-Sibling Map:
════════════════════════════════════════════════════════
document
│
html
/ \
head body
/ \
nav main
/ | \ \
li li li article
| | | / \
a a a h2 p
nav = parent of li elements
li = children of nav
li's = siblings of each other
a = child of each li
════════════════════════════════════════════════════════Traversing Up — Finding Parents
<ul id="menu">
<li class="item"><a id="home-link" href="/">Home</a></li>
<li class="item"><a href="/about">About</a></li>
<li class="item"><a href="/contact">Contact</a></li>
</ul>const link = document.getElementById('home-link');
// parentElement — most commonly used
console.log(link.parentElement.tagName); // "LI"
console.log(link.parentElement.className); // "item"
// Chain multiple levels
console.log(link.parentElement.parentElement.id); // "menu"
console.log(link.parentElement.parentElement.tagName); // "UL"
// parentNode vs parentElement
console.log(link.parentNode === link.parentElement); // true (for elements)
// Special case: parentNode on <html> element
console.log(document.documentElement.parentNode); // #document
console.log(document.documentElement.parentElement); // null (no element parent!)"LI" "item" "menu" "UL" true #document null
Traversing Down — Finding Children
3 "H2" "Description here" 9 "card-title" "btn-buy" "Buy Now" 3 "\n " Child 0: <h2> "Product Name" Child 1: <p> "Description here" Child 2: <button> "Buy Now"
Before/After Visual: children vs childNodes
Traversing Sideways — Finding Siblings
<ul id="steps">
<li id="step1" class="step done">Step 1: Planning</li>
<li id="step2" class="step active">Step 2: Development</li>
<li id="step3" class="step">Step 3: Testing</li>
<li id="step4" class="step">Step 4: Deployment</li>
</ul>const activeStep = document.getElementById('step2');
// Next sibling
console.log(activeStep.nextElementSibling.id); // "step3"
console.log(activeStep.nextElementSibling.textContent); // "Step 3: Testing"
// Previous sibling
console.log(activeStep.previousElementSibling.id); // "step1"
console.log(activeStep.previousElementSibling.className);// "step done"
// Chain siblings
const step4 = activeStep.nextElementSibling.nextElementSibling;
console.log(step4.id); // "step4"
// First step's previous = null (it's the first)
const first = document.getElementById('step1');
console.log(first.previousElementSibling); // null
// Last step's next = null (it's the last)
const last = document.getElementById('step4');
console.log(last.nextElementSibling); // null
// nextSibling vs nextElementSibling
console.log(activeStep.nextSibling.nodeType); // 3 (text whitespace!)
console.log(activeStep.nextElementSibling.nodeType); // 1 (element — correct)"step3" "Step 3: Testing" "step1" "step done" "step4" null null 3 1
closest() — Walk Up to Find an Ancestor
closest() is like parentElement but smarter — it walks up the tree until it finds an ancestor matching a CSS selector.
<div class="card" data-product-id="42">
<div class="card-body">
<h3>Product Title</h3>
<div class="actions">
<button class="btn-delete" data-action="delete">Delete</button>
</div>
</div>
</div>"Card found! Product ID: 42" null true "DIV" "DIV" "42"
contains() — Check if Element is a Descendant
const nav = document.querySelector('nav');
const link = document.querySelector('nav a');
const footer = document.querySelector('footer');
console.log(nav.contains(link)); // true — link IS inside nav
console.log(nav.contains(footer)); // false — footer is NOT inside nav
console.log(nav.contains(nav)); // true — element contains itself!true false true
Complete Traversal Cheat Sheet
═══════════════════════════════════════════════════════════════
Property/Method │ Goes To │ Returns
═══════════════════════════════════════════════════════════════
.parentElement │ One level UP │ Element or null
.parentNode │ One level UP │ Node or null
.children │ Direct children │ HTMLCollection
.childNodes │ All child nodes │ NodeList (inc text)
.firstElementChild │ First child el │ Element or null
.lastElementChild │ Last child el │ Element or null
.nextElementSibling │ Next sibling el │ Element or null
.previousElementSibling │ Prev sibling el │ Element or null
.closest(selector) │ Nearest ancestor │ Element or null
.contains(node) │ Check descendant │ Boolean
.childElementCount │ Count children │ Number
═══════════════════════════════════════════════════════════════Real World Use Cases
Common Mistakes
❌ Mistake 1: Using firstChild expecting an element
const ul = document.querySelector('ul');
// ❌ Wrong — gets text/whitespace node (nodeType 3)
const firstItem = ul.firstChild;
console.log(firstItem.tagName); // undefined! It's a text node, not <li>
// ✅ Correct — gets first <li> element
const firstItem2 = ul.firstElementChild;
console.log(firstItem2.tagName); // "LI"❌ Mistake 2: Assuming nextSibling is an element
const li = document.querySelector('li');
// ❌ May give a text node (whitespace between tags)
console.log(li.nextSibling.tagName); // TypeError: Cannot read properties of text node
// ✅ Always use nextElementSibling
console.log(li.nextElementSibling.tagName); // "LI"❌ Mistake 3: Not checking for null before chaining
// ❌ Dangerous — last element has no nextElementSibling
const last = ul.lastElementChild;
console.log(last.nextElementSibling.textContent); // TypeError: Cannot read... of null
// ✅ Safe — check before using
const next = last.nextElementSibling;
if (next) {
console.log(next.textContent);
}Interview Questions
Q1. What is the difference between parentNode and parentElement? > Both usually return the same thing for elements. The difference appears at the top of the tree: document.documentElement.parentNode returns the #document object, but .parentElement returns null because the document node is not an element.
Q2. Why does childNodes.length usually give a larger number than children.length? > childNodes includes ALL child nodes: element nodes, text nodes (whitespace between tags), and comment nodes. children includes only element nodes (nodeType 1). Whitespace between HTML tags creates extra text nodes.
Q3. What does closest() do and when would you use it? > closest(selector) walks UP the DOM tree from the current element (including itself) and returns the first ancestor matching the selector. It's commonly used in event delegation — e.g., a button click inside a card needs to find the parent .card container.
Q4. What is the difference between children and childNodes? > children is an HTMLCollection containing only Element nodes (type 1). childNodes is a NodeList containing ALL node types including text nodes (type 3) and comment nodes (type 8).
Q5. How would you get all sibling elements of a given element? > Use element.parentElement.children to get all children of the parent, then filter out the element itself: Array.from(el.parentElement.children).filter(c => c !== el).
Q6. Does closest() check the element itself or only its ancestors? > It starts checking the element itself first, then moves up to ancestors. So el.closest('.active') returns el itself if el has the .active class.
Key Takeaways
✅ Use Element properties (children, firstElementChild) — not Node properties
✅ firstChild and nextSibling often return whitespace text nodes — avoid them
✅ closest() walks UP the tree — perfect for event delegation patterns
✅ children returns a LIVE HTMLCollection, querySelectorAll returns a STATIC NodeList
✅ Always check for null before chaining traversal properties
✅ childNodes.length > children.length because of whitespace text nodes
✅ DOM traversal avoids re-querying the document — it's fasterExam Focus
Revise definitions, diagrams, examples, and short-answer points for JavaScript DOM Traversal - Navigate Parent, Child & Sibling Nodes.
Interview Use
Prepare one clear explanation, one practical example, and one common mistake for this JavaScript Master Course topic.
Search Terms
javascript-complete-guide, javascript master course, javascript, complete, guide, dom, traversal, javascript dom traversal - navigate parent, child & sibling nodes
Related JavaScript Master Course Topics