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 / querySelectorAll are 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: id should 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"], :hover is 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 NodeList has forEach; for older patterns use Array.from(rows) or spread [...rows].

6. Comparison table

APIReturnsLive?Notes
getElementByIdElement | nulln/aSingle element
getElementsByTagNameHTMLCollectionYesTag name
getElementsByClassNameHTMLCollectionYesSpace-separated classes
querySelectorElement | nulln/aCSS selector
querySelectorAllNodeListNo (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

  1. getElementById — simplest, fastest ID lookup.
  2. getElementsBy*live collections; remember they mutate as the DOM changes.
  3. querySelector / querySelectorAllCSS-powered; NodeList from querySelectorAll is a snapshot.

Explain-It Challenge

Explain without notes:

  1. What is the practical difference between a live HTMLCollection and a static NodeList from querySelectorAll?
  2. Why should id values be unique in a document?
  3. Write a one-liner that selects the first button inside #toolbar (your choice of API).

Navigation: ← 1.14.b — DOM Structure · 1.14.d — Tree Traversal →