The DOM: finding and changing elements

JavaScript · Essentials · 12 min

The DOM is how JavaScript reads and updates what the user sees on a web page.

When a browser loads HTML it builds the DOM (Document Object Model): a tree of objects, one per element and text node, rooted at document. Changing those objects changes the page.

Find elements with CSS selectors:

  • document.querySelector(sel) — the first match, or null.
  • document.querySelectorAll(sel) — a static NodeList of all matches (it has forEach and works with for...of).
  • Both also exist on elements, to search inside them: form.querySelector("input").

Change what an element shows:

  • el.textContent = "..." sets plain text. Safe with user input.
  • el.innerHTML = "..." parses a string as HTML. Never use it with untrusted data — that is how cross-site scripting (XSS) happens.
  • el.classList.add/remove/toggle("active") for styling via CSS classes; prefer this to setting el.style directly.
  • el.setAttribute("aria-expanded", "true"), el.hidden = true, input.value, img.src.
  • el.dataset.userId reads a data-user-id attribute.

Create and insert elements with document.createElement("li"), then parent.append(child) (also accepts strings), prepend, before, after, or replaceWith. Remove with el.remove().

When you add many elements, build them first and append once (or use a DocumentFragment) so the browser updates layout once rather than many times.

Your script must run after the elements exist — use type="module" or defer on the script tag. If querySelector returns null, the element wasn't in the DOM yet or the selector is wrong.

Example

// Assumes: <ul id="todos"></ul> <p class="status"></p>
const list = document.querySelector("#todos");
const status = document.querySelector(".status");

const todos = ["Learn the DOM", "Handle events"];
for (const text of todos) {
  const li = document.createElement("li");
  li.textContent = text;            // safe: never parsed as HTML
  li.dataset.done = "false";        // data-done="false"
  list.append(li);
}

status.textContent = `${todos.length} todos`;
status.classList.add("visible");

document.querySelectorAll("#todos li").forEach((li, i) => {
  if (i === 0) li.classList.add("first");
});

Remember

  • querySelector/querySelectorAll find elements with CSS selectors
  • Use textContent for text; innerHTML with user data is an XSS hole
  • Toggle classList instead of setting inline styles

Watch out for

  • Running the script before the HTML is parsed, so querySelector returns null.

Check yourself

  1. You want to show a user's comment inside a <p>. Which is the safe choice?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model/Introduction