⚡JavaScript
Lesson 34 of 117
25 min
Selecting & Manipulating
querySelector, classList, dataset, traversal.
The DOM is the live, in-memory tree of nodes that represents your HTML page. Every <div>, every attribute, every bit of text is a node. JavaScript can read, change, add, and remove nodes, and the browser repaints accordingly. This lesson covers the essentials you'll use every day.
Finding elements
js
// By id (fastest, returns one element or null)
const header = document.getElementById("page-header");
// CSS selector (most flexible, returns first match or null)
const firstBtn = document.querySelector(".btn");
const navItem = document.querySelector("nav > ul > li");
// All matches (returns a static NodeList)
const allBtns = document.querySelectorAll(".btn");
allBtns.forEach(btn => btn.classList.add("ready"));When to use which
Use
getElementById when you know the id (fast and intent-clear). Use querySelector / querySelectorAll for everything else. The CSS-selector version is the modern default.Reading and writing content
js
const el = document.querySelector("#message");
// Read
el.textContent // plain text inside the element
el.innerHTML // HTML markup inside (parsed when set)
// Write
el.textContent = "Hello, world";
el.innerHTML = "<strong>Hello</strong>, world";textContent vs innerHTML: XSS
Setting
innerHTML from any user input is a classic cross-site scripting hole. Strings with <script> or event handlers will execute. Default to textContent. Reach for innerHTMLonly when you fully trust the source (or you've sanitized it).Classes, attributes, data
js
const el = document.querySelector(".card");
// Classes
el.classList.add("active");
el.classList.remove("loading");
el.classList.toggle("open");
el.classList.contains("active"); // true
// Attributes (the raw HTML attribute)
el.getAttribute("href");
el.setAttribute("href", "/new-url");
el.removeAttribute("disabled");
// data-* attributes get auto-camelCased into .dataset
// <div data-user-id="42"> → el.dataset.userId === "42"
el.dataset.userId = "99"; // sets data-user-id="99"
// Inline styles (object form of CSS)
el.style.color = "red";
el.style.backgroundColor = "papayawhip";Creating and inserting nodes
js
// 1. Build a node
const li = document.createElement("li");
li.textContent = "New item";
li.classList.add("todo");
// 2. Insert it somewhere
const list = document.querySelector("#todos");
list.appendChild(li); // at the end
list.prepend(li); // at the start (modern)
list.insertBefore(li, list.firstChild); // old-school version of prepend
// Bulk insert from a string (parsed once)
list.insertAdjacentHTML(
"beforeend",
"<li class='todo'>Another one</li>"
);
// Move or remove
li.remove(); // pop it out
otherList.appendChild(li); // moving is a single appendTraversal
js
const el = document.querySelector(".card");
el.parentElement // parent (skips text nodes)
el.children // HTMLCollection of element children
el.firstElementChild
el.lastElementChild
el.previousElementSibling
el.nextElementSibling
// Need an ancestor matching a selector?
el.closest(".container") // walks up until it matches.closest is gold
Use
.closest(selector)whenever you need to find a wrapping element. It's the cleanest way to handle event delegation, scoped lookups, and "which row was clicked" questions.Document fragments: batch inserts
Inserting nodes one by one in a tight loop triggers a layout pass each time. A DocumentFragment is a temporary container that lets you build a tree off-screen and insert it once:
js
const frag = document.createDocumentFragment();
for (const item of items) {
const li = document.createElement("li");
li.textContent = item.label;
frag.appendChild(li);
}
document.querySelector("#list").appendChild(frag); // one layout passTry it: live DOM manipulation
The playground below has a small todo list. Add items with the input, click an item to mark it done, click the X to remove it. Open it, then change the styling, add a counter, whatever you want.
Quiz
Quiz1 / 3
What's the safest way to set user-provided text in an element?
Recap
getElementByIdfor ids,querySelector(All)for everything else.textContentby default.innerHTMLonly for trusted content. XSS lurks here.classList,dataset, andstyleare the modern way to mutate elements.createElement+appendChild/prepend/insertAdjacentHTMLfor building nodes..closestis the most underrated DOM method. Use it for delegation and scoped lookups.