Before you can change something on the page, you have to find it. JavaScript gives you several ways to grab elements from the DOM.
getElementById
If an element has an id attribute, you can grab it directly:
const title = document.getElementById("title");
console.log(title);
The console will show the <h1> element. Note that you write just the id name, "title", without a #. Each id should be unique on a page, so this always gives you one element.
querySelector: the Swiss Army knife
document.querySelector() is more flexible. It takes a CSS selector (the same patterns you use in CSS to style things) and returns the first element that matches:
const title = document.querySelector("#title"); // by id (with #)
const firstIntro = document.querySelector(".intro"); // by class (with .)
const firstItem = document.querySelector("li"); // by tag name
const favorite = document.querySelector("#food-list .favorite"); // nested
If you don't know CSS selectors yet, here are the ones you'll use 95% of the time:
| Selector | Matches | Example |
|---|---|---|
tag | Every element with that tag | "p", "li", "button" |
.name | Elements with that class | ".intro", ".favorite" |
#name | The element with that id | "#title", "#photo" |
parent child | child elements inside parent | "#food-list li" |
tag.name | That tag with that class | "li.favorite" |
[attr] | Elements with that attribute | "[disabled]", "[type='email']" |
querySelectorAll: grab them all
To get every matching element, use querySelectorAll(). It returns a list (called a NodeList) that you can loop over with forEach or for...of:
const items = document.querySelectorAll("#food-list li");
console.log(items.length); // 3
items.forEach((item) => {
console.log(item.textContent);
});
// Burger
// Omelet
// Pancakes
A NodeList looks and acts a lot like an array, and it has length, forEach and index access (items[0]). But it doesn't have all the array methods (no map or filter). If you need those, convert it with Array.from(items) or [...items].
If nothing matches your selector, querySelector gives back null. And if you then try to do something with it, you get the famous error:
Uncaught TypeError: Cannot read properties of null (reading 'textContent')
When you see this, check three things: (1) Is the selector spelled correctly, with the right # or .? (2) Does the element actually exist in the HTML? (3) Is your <script> tag at the bottom of the <body>? If the script runs before the element is created, the element doesn't exist yet! (Remember the Professor's Corner from Kindergarten.)