Selecting DOM Elements

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.

selecting-elements.js
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 the title variable.
  • 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.

selecting-elements.js
const title = document.querySelector("#main-title"); // by id
const 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 the card class.
  • 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.

selecting-elements.js
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 card class and stores them all in the cards NodeList.
  • The console.log(cards.length) line reports how many elements matched.
  • The forEach loop runs once per element, logging each card in 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.

selecting-elements.js
const cards = document.getElementsByClassName("card"); // by class
const headings = document.getElementsByTagName("h2"); // by tag

Both lines collect every matching element:

  • The first line gathers all elements that have the card class.
  • 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.

index.html
<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.

selecting-elements.js
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-heading id selector.
  • The second line selects the button using the .action-btn class selector.
  • The two console.log lines 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
selecting-elements.js
// ❌ Class selector without the dot looks for a <card> tag
const wrong = document.querySelector("card");
// βœ… Use the dot to select by class
const right = document.querySelector(".card");

These two lines look almost the same but behave very differently:

  • The wrong line passes "card" with no dot, so the browser hunts for a <card> tag that does not exist and returns null.
  • The right line passes ".card" with the dot, so it correctly selects the first element that has the card class.

πŸ”§ Try It Yourself!

  1. Add an <h1> with an id and a <button> with a class to an HTML page.
  2. Select the heading with getElementById and log it to the console.
  3. Select the same heading with querySelector using the #id syntax.
  4. Add a few elements that share a class, select them all with querySelectorAll, and log the NodeList’s length.
  5. 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
  • βœ… getElementById finds one element by its id, with no #
  • βœ… querySelector returns the first match for a CSS selector, or null
  • βœ… querySelectorAll returns a NodeList of every match
  • βœ… querySelector and querySelectorAll are 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.

Share & Connect