20. JavaScript DOM Selecting Elements
What you will learn
- How to find elements by id, class, tag, and CSS selector
- The difference between one element and a list of elements
- How to loop through a selection
- How to move around the tree
Why select elements?
Before JavaScript can change anything on a page, it has to find the element. The methods below do that. The two most useful are querySelector and querySelectorAll, because they use the same CSS selectors you already know.
Overview of methods
| Method | Returns |
|---|---|
getElementById("id") |
One element, or null |
querySelector("selector") |
The first matching element, or null |
querySelectorAll("selector") |
A list of all matching elements (it may be empty) |
getElementsByClassName("class") |
A live list of elements with that class |
getElementsByTagName("tag") |
A live list of elements with that tag |
For new code, getElementById, querySelector, and querySelectorAll cover almost everything.
By id
Example
<h2 id="main-title">Original</h2>
<script>
const title = document.getElementById("main-title");
title.textContent = "Found by id";
</script>
Output (after the script runs)
Found by id
Notice there is no # in getElementById. You pass just the name.
By CSS selector
querySelector takes any CSS selector, including the # for ids, the dot for classes, and combinations. It returns the first match.
Example
<p class="note">First note</p>
<p class="note">Second note</p>
<div id="box"><p>Paragraph inside the box</p></div>
<script>
document.querySelector(".note").style.color = "crimson"; // first note only
document.querySelector("#box p").style.fontWeight = "bold"; // p inside #box
</script>
Output (after the script runs)
First note
Second note
Paragraph inside the box
Selecting many elements
querySelectorAll returns a list. Loop through it to change every match.
Example
<ul>
<li class="item">One</li>
<li class="item">Two</li>
<li class="item">Three</li>
</ul>
<script>
const items = document.querySelectorAll(".item");
items.forEach(function (item, index) {
item.textContent = (index + 1) + ". " + item.textContent;
item.style.color = "#0d6efd";
});
</script>
Output (after the script runs)
- 1. One
- 2. Two
- 3. Three
A list from querySelectorAll supports forEach and for...of, and has a length. To use array methods such as map or filter, first convert it with Array.from(items).
One or many: the classic mistake
querySelectorAll returns a list, so this fails:
Example: this does not work
document.querySelectorAll(".item").style.color = "red"; // Error: a list has no style
Loop through the list instead, or use querySelector when you want just one.
Always check for null
If nothing matches, getElementById and querySelector return null, and using it crashes the script. Guard against it when an element might not exist:
Example
<p id="demo"></p>
<script>
const missing = document.querySelector("#does-not-exist");
if (missing) {
missing.textContent = "Found it";
} else {
document.getElementById("demo").textContent = "That element is not on this page.";
}
</script>
Output (after the script runs)
That element is not on this page.
Searching inside an element
You can call querySelector on any element to search only inside it.
Example
<div id="a"><p class="msg">Message in A</p></div>
<div id="b"><p class="msg">Message in B</p></div>
<script>
const box = document.getElementById("b");
box.querySelector(".msg").style.background = "yellow"; // only inside #b
</script>
Output (after the script runs)
Message in A
Message in B
Moving around the tree
From one element you can reach its relatives.
| Property | Gives you |
|---|---|
parentElement |
The parent element |
children |
The child elements |
firstElementChild, lastElementChild |
First and last child element |
nextElementSibling, previousElementSibling |
The element after and before |
closest("selector") |
The nearest ancestor that matches |
Example
<ul id="list">
<li>One</li>
<li id="two">Two</li>
<li>Three</li>
</ul>
<p id="demo"></p>
<script>
const two = document.getElementById("two");
document.getElementById("demo").innerHTML =
"Parent id: " + two.parentElement.id + "<br>" +
"Before: " + two.previousElementSibling.textContent + "<br>" +
"After: " + two.nextElementSibling.textContent + "<br>" +
"Items in the list: " + two.parentElement.children.length;
</script>
Output (after the script runs)
- One
- Two
- Three
Parent id: list
Before: One
After: Three
Items in the list: 3
Common mistakes
- Adding
#or.togetElementById. It takes the bare name. - Forgetting the
#or.inquerySelector. - Treating the list from
querySelectorAllas a single element. - Not checking for
nullwhen the element may be missing. - Running the script before the elements exist.
Exercise
Select every paragraph with the class tip and give each a lightyellow background. The normal paragraph must stay unchanged.
Show solution
<p class="tip">Tip one</p>
<p class="tip">Tip two</p>
<p>Normal text</p>
<script>
const tips = document.querySelectorAll(".tip");
tips.forEach(function (tip) {
tip.style.backgroundColor = "lightyellow";
});
</script>
Knowledge check
1. Which method returns only the first match for a CSS selector?
querySelector()
2. What does querySelector return when nothing matches?
null
3. Why does document.querySelectorAll(".x").style.color = "red" fail?
It returns a list, and a list has no style. You must loop through it.
Summary
- Use
getElementById,querySelector, andquerySelectorAllto find elements. - Remember: one element or a list, and check for
null. - Reach relatives with
parentElement,children, and sibling properties.