Selecting DOM Elements
Table of Contents + β
In the previous lesson, we learned that the DOM turns your HTML page into objects JavaScript can read and change. Now letβs learn the first step of any DOM work: selecting the element you want.
π― Why Select an Element First?
Before you can change an element, you have to find it. Selecting an element gives you a reference to it, and you store that reference in a variable so you can read or change it later.
JavaScript gives you several methods on the document object to find elements. Each one searches the page in a slightly different way.
| Method | What it selects | Returns |
getElementById | The element with a matching id | One element, or null |
querySelector | The first element matching a CSS selector | One element, or null |
querySelectorAll | Every element matching a CSS selector | A NodeList of elements |
getElementsByClassName | Every element with a matching class | A live HTMLCollection |
getElementsByTagName | Every element of a tag name | A live HTMLCollection |
π Selecting by ID
The getElementById method finds the single element whose id matches. You pass the id name only, with no # in front of it.
const title = document.getElementById("main-title");console.log(title); // <h1 id="main-title">...</h1>Letβs walk through what each line does:
- The first line calls
getElementById("main-title")and stores the matching element in thetitlevariable. - The second line logs that element, so we can confirm in the console that we grabbed the right
<h1>.
Because an id is meant to be unique on a page, this method returns just one element.
π querySelector: One Match
The querySelector method takes any CSS selector and returns the first element that matches. This is the modern, flexible choice because you select the same way you do in CSS.
You write the selector exactly as you would in a stylesheet: #id for an id, .class for a class, and a plain name for a tag.
const title = document.querySelector("#main-title"); // by idconst box = document.querySelector(".card"); // by class (first one)const firstButton = document.querySelector("button"); // by tag (first one)Each line shows a different selector style:
- The first line passes
"#main-title", so it matches the element with that id. - The second line passes
".card", so it matches the first element that has thecardclass. - The third line passes
"button", a plain tag name, so it matches the first<button>on the page.
When several elements match, querySelector gives you only the first one in the page.
querySelector can return null
If nothing matches your selector, querySelector returns null instead of
an element. Reading a property off null throws an error, so check the result
before you use it.
π querySelectorAll: Every Match
When you need all matching elements, use querySelectorAll. It returns a NodeList, which is a list-like collection of every element that matches.
A NodeList is not an array, but you can loop over it with forEach.
const cards = document.querySelectorAll(".card");
console.log(cards.length); // how many matched
cards.forEach((card) => { console.log(card);});Here is what each part does:
- The first line selects every element with the
cardclass and stores them all in thecardsNodeList. - The
console.log(cards.length)line reports how many elements matched. - The
forEachloop runs once per element, logging eachcardin turn so we can see every match.
Unlike querySelector, this method never returns null. If nothing matches, you get an empty NodeList with a length of 0.
π The Older getElementsBy Methods
You may still see getElementsByClassName and getElementsByTagName in older code. They return a live HTMLCollection, which updates automatically as the page changes.
const cards = document.getElementsByClassName("card"); // by classconst headings = document.getElementsByTagName("h2"); // by tagBoth lines collect every matching element:
- The first line gathers all elements that have the
cardclass. - The second line gathers all
<h2>headings by their tag name.
These work fine, but querySelector and querySelectorAll cover the same cases with one consistent CSS syntax, so prefer them in new code.
π§ͺ A Practical Example
Here you select a heading by its id and a button by its class, then log both to confirm you found them.
<h1 id="page-heading">Welcome</h1><button class="action-btn">Click me</button>This markup gives us two targets to select: an <h1> with the id page-heading and a <button> with the class action-btn.
const heading = document.querySelector("#page-heading");const button = document.querySelector(".action-btn");
console.log(heading); // <h1 id="page-heading">Welcome</h1>console.log(button); // <button class="action-btn">Click me</button>Letβs read this top to bottom:
- The first line selects the heading using the
#page-headingid selector. - The second line selects the button using the
.action-btnclass selector. - The two
console.loglines print each element so we can confirm both references point to the right nodes.
With these references stored in variables, you are ready to change their content or respond to clicks, which we cover next.
β οΈ Common Mistakes to Avoid
| Mistake | Problem | Solution |
Forgetting the # or . in querySelector | querySelector("card") looks for a <card> tag, not a class | Write .card for a class and #card for an id |
Adding # to getElementById | getElementById("#title") matches nothing | Pass the id name only: getElementById("title") |
| Using an element that was not found | null throws an error when you read its properties | Check if (element) before using it |
| Running the script before the DOM is ready | Elements lower in the page do not exist yet, so you get null | Put the script at the end of <body> or use defer |
// β Class selector without the dot looks for a <card> tagconst wrong = document.querySelector("card");
// β
Use the dot to select by classconst right = document.querySelector(".card");These two lines look almost the same but behave very differently:
- The
wrongline passes"card"with no dot, so the browser hunts for a<card>tag that does not exist and returnsnull. - The
rightline passes".card"with the dot, so it correctly selects the first element that has thecardclass.
π§ Try It Yourself!
- Add an
<h1>with anidand a<button>with aclassto an HTML page. - Select the heading with
getElementByIdand log it to the console. - Select the same heading with
querySelectorusing the#idsyntax. - Add a few elements that share a class, select them all with
querySelectorAll, and log the NodeListβslength. - Try selecting an element that does not exist and confirm you get
null.
π§© What Youβve Learned
- β You must select an element before you can change it
- β
getElementByIdfinds one element by its id, with no# - β
querySelectorreturns the first match for a CSS selector, ornull - β
querySelectorAllreturns a NodeList of every match - β
querySelectorandquerySelectorAllare the modern, flexible choice - β
Use
#for ids,.for classes, and a plain name for tags
π Whatβs Next?
Now that you can select elements, letβs change what they show on the page. Continue to Changing Content.