What do we mean when we say that the DOM is a tree? Are we saying it has leaves?
Well, yes, metaphorically.
Trees make a good metaphor for the DOM because we intuitively understand how we might traverse them. Starting at the roots, one can climb up the tree and out to the farthest — and thinnest — branches.
The thicker a branch is, the stronger its connections are: the more it holds within it.
Likewise, the thinner a branch is, the less it holds inside.
The DOM works basically the same way, except we usually talk about the root as being at the top of the DOM and the leaves being the most deeply nested HTML elements. So basically, we can imagine a tree turned on its head.
An interesting property of trees is that every tree can contain subtrees, which we can, for all intents and purposes, treat independently of their parent trees.
Practically speaking, the DOM begins at
<html>, but we should think carefully about manipulating what's between the
<head></head> tags. Instead, we can look at the DOM subtree with its root at
<body> and only deal with things that will be visible on the page. Within that tree, we might also deal with subtrees. So, for example, if we have
<body> <div> <p>Hi!</p> </div> <div> <p>Bye!</p> </div> </body>
We would have a tree that looks like
body / \ div div / \ p p / \ "Hi!" "Bye!"
Pretty simple, right? Similarly, if we had a DOM subtree that looked like
<div> <div> <h1>Hello!</h1> </div> <div> <h5>Sup?</h5> </div> </div>
We could simply treat it as the tree
div / \ div div / \ h1 h5 / \ "Hello!" "Sup?"
Remember when we said that we could organize our tree in such a way that a node's metadata didn't interfere with finding its children? It turns out that not only does providing additional information about a node make it more useful, it also makes it easier to find.
This method provides the quickest access to a node, but it requires that we know something very specific about it — its
id. Since IDs must be unique, this method only returns one element. (If you have two elements with the same ID, this method returns the first one — keep your IDs unique!) Given the following DOM tree
<div> <h5 id="greeting">Hello!</h5> </div>
we could find the
h5 element with
document.getElementById('greeting'). Notice how the
id that we pass to
getElementById is identical to the
<h5 id="greeting">. We can assign properties to HTML nodes (or elements) simply by including them between the
<> tags at the start of the element (so not in the
</h5> tag, in this case).
Try it out!
Open up your web inspector (command+option+j on OS X) and find an element on the page — make note of its
id. Then open up your console, type
document.getElementById('theIdYouTookNoteOf'), and check out your handy dandy DOM node. Try changing a few of its properties!
This method, as its name implies, finds elements by their
className does not need to be unique; as such, this method returns an HTMLCollection (basically a list of DOM nodes — note that it is not an array, even though it has a
length property) of all the elements with the given class. You can iterate over an HTMLCollection with a simple
Given the following DOM tree
<!-- the `className` attribute is called `class` in HTML -- it's a bummer --> <div> <div class="banner"> <h1>Hello!</h1> </div> <div class="banner"> <h1>Sup?</h1> </div> <div class="banner"> <h5>Tinier heading</h5> </div> </div>
we could find all of the elements with
className === 'banner' by calling
Try it out!
Inspect the web page again, this time making note of a className. Get all elements with that className and give 'em a look. Remember, you can use a
for loop to loop through them. (You can also assign the return value of
document.getElementsByClassName() to a variable:
var elements = document.getElementsByClassName('banner').)
Suppose you don't know an element's ID but you do know its tag name (the tag name is the main thing between the
'h1', etc.). Since tag names aren't unique, this method returns an HTMLCollection of 0 to many nodes with the given tag.
Try it out!
Explore the DOM in console by typing
document.getElementsByTagName('div'). Remember, you can iterate through these elements using a simple
What if we know next to nothing about an element? Or what if we're just interested in finding out more about the child nodes of a given element? This is where our knowledge of trees and nested data structures comes in handy!
Given the following DOM tree (which you can find in
index.html — feel free to open the file up in your browser to play along!)
<main> <div> <div> <p>Hello!</p> </div> </div> <div> <div> <p>Hello!</p> </div> </div> <div> <div> <p>Hello!</p> </div> </div> </main>
how would we go about changing only the second "Hello!" to "Goodbye!"? We couldn't just iterate over
document.getElementsByTagName('div'), checking for
textContent === "Hello!", because we'd inadvertently change all three "Hello!"s. More importantly, the DOM might change (more on that later), and we want to make sure that we're updating the right element.
Let's start by getting the
const main = document.getElementsByTagName('main')
Then we can get the children of
main.children, so we can get the second child with
const div = main.children
Finally, we can get and update our
<p> element with
// we can call getElementsByTagName() on an _element_ // to constrain the search to its children! const p = div.getElementsByTagName('p') p.textContent = "Goodbye!"
Obviously, this way of accessing that text isn't fully generic, but it does a good job of demonstrating the basic tools available to us for finding and manipulating HTML elements.
View The DOM is a Tree on Learn.co and start learning to code for free.