Learning Objectives
- Move between nodes with parent, child, and sibling properties
- Explain why
firstChildandfirstElementChilddiffer, and when it bites - Walk upward to a matching ancestor with
closest() - Traverse a subtree depth-first with
firstChild/nextSibling
Two flavors of every relationship
Indent your markup like a civilized person and every element grows whitespace-only text children. So the tree API splits each relationship in two: the node properties see everything — elements, text, comments — and the element properties skip to tags only.
When you are working with page structure — which is most of the time — use the element flavor and the whitespace never troubles you. Reach for the node flavor only when text nodes are the point, and then check nodeType: 1 is an element, 3 is text, 8 is a comment.
Walking up, and walking everything
parentNode climbs one level. closest() climbs with a selector — from the current element upward, returning the first ancestor (or self) that matches:
That one call is the backbone of event delegation in the Events series: from whatever small thing was clicked, walk up to the component that owns it. And with just firstChild and nextSibling you can visit an entire subtree — the depth-first walk every serializer, sanitizer, and framework diff is built on:
Live demo
A small nested tree — a list inside a div inside a div — with each traversal one button press. Whatever a walk reaches gets marked in the sample, so you can check your prediction against the tree. Pay attention to section 2: firstChild versus firstElementChild on the same element, and the childNodes dump where the whitespace text nodes finally show themselves. Then run the depth-first walk and read the indented output against the markup.
Walk or query?
Both reach nodes; they answer different questions. A query answers “find me the nodes matching this description, wherever they are.” A walk answers “from the node I am holding, give me its neighbor.” Inside a delegated event handler, holding the element that was clicked, closest() and children are the natural moves — re-querying the whole document to find where you already are is the roundabout version.
Next Steps
You can reach any node in the tree. In Step 4: Attributes and mappings, we start changing what we find:
- Read and write attributes with
getAttribute/setAttribute - Meet the property mapping — and the renamed reserved words like
classNameandhtmlFor - Flip visual state with
classList - Attach your own data with
data-*and read it back throughdataset