Selecting Elements
Before you can change the DOM, you need references to the elements you care about. Today you’ll learn the most common selection methods, how CSS selectors power them, and when to pick each tool.
Step 1: The document Object
documentis your gateway to the DOM.- Selection methods return single elements, collections, or live lists.
- Always guard against
nullresults—your selector might not match anything.
Step 2: getElementById
Fastest when you know the unique ID.
<h1 id="title">Dashboard</h1>const heading = document.getElementById("title");
console.log(heading); // <h1 id="title">Dashboard</h1>- Returns a single element or
null. - IDs must be unique, so this is great for top-level anchors.
Step 3: querySelector
Accepts any CSS selector and returns the first match.
const firstCard = document.querySelector(".card");
const navLink = document.querySelector("nav a.active");- Supports complex selectors (descendant, attribute, pseudo-classes).
- Useful when multiple elements share class names but you only need one (e.g., the first match).
Step 4: querySelectorAll
Returns a static NodeList of every match.
const buttons = document.querySelectorAll("button.primary");
buttons.forEach((button) => {
button.addEventListener("click", handleClick);
});NodeListsupportsforEach, spread syntax, and indexing.- Static means it won’t auto-update if the DOM changes after selection.
Step 5: Legacy Collections
getElementsByClassName("card")getElementsByTagName("li")
These return live HTMLCollection objects that update as the DOM changes. Still useful, but be mindful that they don’t support forEach directly—convert with Array.from(...) if needed.
Step 6: Traversing Relationships
Once you have an element, move relative to it.
const card = document.querySelector(".card");
const parent = card.parentElement;
const children = card.children;
const firstChild = card.firstElementChild;
const next = card.nextElementSibling;- Use traversal to stay scoped and avoid querying the entire document repeatedly.
Step 7: Guarding Against null
Selections can fail—always check before using the result.
const banner = document.querySelector(".banner");
if (banner) {
banner.classList.add("visible");
} else {
console.warn("Banner not found");
}This prevents runtime errors when elements don’t exist or load conditionally.
Step 8: Selecting Within Containers
Query a specific subtree to limit matches.
const sidebar = document.querySelector(".sidebar");
const links = sidebar.querySelectorAll("a");- Helpful in components where class names repeat.
- Improves performance on large pages.
Step 9: Practice Prompts
- Select the element with ID
heroand log itstextContent. - Use
querySelectorAllto grab all checkboxes inside a form and print how many are checked. - Convert
document.getElementsByClassName("card")into an array and remove the"hidden"class from each. - Implement a function
findNavLinks(containerSelector)that returns all<a>elements inside the chosen container.
Key Takeaways
- ✅
getElementByIdis fastest for unique elements;querySelector/querySelectorAllhandle flexible CSS selectors. - ✅
NodeListfromquerySelectorAllis static; legacy collections are live. - ✅ Check for
nullbefore using selected elements. - ✅ Scope queries within components to keep DOM work efficient.
🎯 Quick Check
- When should you prefer
getElementByIdoverquerySelector? - How do you iterate over the results of
querySelectorAll? - What’s the difference between a live
HTMLCollectionand a staticNodeList? - How can you select only the links inside a specific navigation bar?
Next lesson: modify content, attributes, and styles once you’ve grabbed the right elements. 🎨