Episode 1 — Fundamentals / 1.14 — DOM Manipulation
1.14.c — Fetching Elements in the DOM
In one sentence: You query the DOM with ID, tag, class, or CSS selector APIs —
querySelector/querySelectorAllare the most flexible; older methods remain common in legacy code and interviews.
Navigation: ← 1.14.b — DOM Structure · 1.14.d — Tree Traversal →
1. document.getElementById(id)
Returns the first element with that id, or null.
const el = document.getElementById("app");
- Fast — browsers index IDs.
- HTML rule:
idshould be unique in the document; duplicates are invalid HTML and behavior is not guaranteed.
2. document.getElementsByTagName(localName)
Returns a live HTMLCollection of all matching elements (e.g. "div", "p").
const paragraphs = document.getElementsByTagName("p");
- Live: if you add/remove matching nodes, the collection updates automatically.
- Access by index:
paragraphs[0].
3. document.getElementsByClassName(classNames)
Returns a live HTMLCollection.
const items = document.getElementsByClassName("card");
const featured = document.getElementsByClassName("card featured"); // both classes
- Argument is one string with space-separated class names (all must be present on the element).
4. document.querySelector(selector)
Returns the first Element matching a CSS selector, or null.
const btn = document.querySelector("#save-btn");
const firstError = document.querySelector(".field .error");
- Supports complex selectors (
>,+,[data-state="open"],:hoveris not useful for static query — use for stateful pseudo-classes carefully). - Runs left-to-right like CSS matching; very broad selectors on huge trees can be slower — be specific.
5. document.querySelectorAll(selector)
Returns a static NodeList of all matches (may be empty).
const rows = document.querySelectorAll("table.data tbody tr");
rows.forEach((tr) => { /* ... */ });
- Static: changes to the DOM do not update the list you already have (re-query if needed).
- Modern
NodeListhasforEach; for older patterns useArray.from(rows)or spread[...rows].
6. Comparison table
| API | Returns | Live? | Notes |
|---|---|---|---|
getElementById | Element | null | n/a | Single element |
getElementsByTagName | HTMLCollection | Yes | Tag name |
getElementsByClassName | HTMLCollection | Yes | Space-separated classes |
querySelector | Element | null | n/a | CSS selector |
querySelectorAll | NodeList | No (static snapshot) | All matches |
7. Scoping queries
Any Element can root a search:
const form = document.querySelector("#signup");
const inputs = form.querySelectorAll("input[name]");
Prefer scoping to reduce work and accidental global matches.
8. Key takeaways
getElementById— simplest, fastest ID lookup.getElementsBy*— live collections; remember they mutate as the DOM changes.querySelector/querySelectorAll— CSS-powered;NodeListfromquerySelectorAllis a snapshot.
Explain-It Challenge
Explain without notes:
- What is the practical difference between a live
HTMLCollectionand a staticNodeListfromquerySelectorAll? - Why should
idvalues be unique in a document? - Write a one-liner that selects the first
buttoninside#toolbar(your choice of API).
Navigation: ← 1.14.b — DOM Structure · 1.14.d — Tree Traversal →