Lesson 107 min read

DOM Manipulation

Reach into the webpage and change anything — text, styles, structure, everything

What Is the DOM?

When a browser loads an HTML page, it builds a tree-like model of every element — this model is the Document Object Model (DOM). Think of it like a family tree: the <html> element is the grandparent, <body> is the parent, and all the <div>s, <p>s, and <button>s are children and grandchildren.

JavaScript can read, change, add, or remove any part of this tree. That's how interactive websites work — the HTML stays the same, but JavaScript reshapes the DOM in real time.

Selecting Elements

// querySelector — select the FIRST match (CSS selector syntax)
const title = document.querySelector("h1");
const btn = document.querySelector(".submit-btn");
const form = document.querySelector("#signup-form");
// querySelectorAll — select ALL matches (returns a NodeList)
const allCards = document.querySelectorAll(".card");
console.log(allCards.length); // number of .card elements
// Loop through all matches
allCards.forEach(card => {
console.log(card.textContent);
});
// Other selectors (less common now, but still valid)
const byId = document.getElementById("main");
const byClass = document.getElementsByClassName("item");
const byTag = document.getElementsByTagName("p");
Output
// (depends on the HTML page)

Changing Content, Styles & Attributes

Once you've selected an element, you can change almost anything about it:

  • .textContent — the plain text inside (safe, no HTML parsing)
  • .innerHTML — the HTML content (be careful — can create security issues if used with user input)
  • .style.property — change inline CSS styles
  • .classList — add, remove, or toggle CSS classes
  • .setAttribute() / .getAttribute() — change HTML attributes like src, href, disabled

Modifying Elements

// Changing text and HTML
const heading = document.querySelector("h1");
heading.textContent = "Welcome!";
heading.innerHTML = "Welcome <em>back</em>!"; // parses HTML
// Changing styles
heading.style.color = "tomato";
heading.style.fontSize = "2rem"; // camelCase, not kebab-case!
heading.style.backgroundColor = "#f0f0f0";
// classList — the better way to style
const card = document.querySelector(".card");
card.classList.add("active"); // add a class
card.classList.remove("hidden"); // remove a class
card.classList.toggle("dark-mode"); // add if missing, remove if present
console.log(card.classList.contains("active")); // true
// Attributes
const img = document.querySelector("img");
img.setAttribute("src", "new-photo.jpg");
img.setAttribute("alt", "A cute puppy");
console.log(img.getAttribute("alt")); // "A cute puppy"
Output
// Elements on page are updated visually
true
A cute puppy

Creating Elements & Handling Events

You can build new HTML elements entirely from JavaScript and insert them into the page. This is how dynamic content works — like adding a new comment, a new todo item, or a notification.

Event listeners let your code react to user actions — clicks, key presses, form submissions, mouse movements, and more. You attach a listener to an element, and JavaScript calls your function whenever that event happens.

Event delegation is a pro technique: instead of adding listeners to every child element, you add ONE listener to the parent and check which child was clicked. This is faster and works even for elements added later.

Creating Elements & Event Listeners

// Creating and adding elements
const list = document.querySelector("#todo-list");
function addTodo(text) {
const li = document.createElement("li");
li.textContent = text;
li.classList.add("todo-item");
list.appendChild(li);
}
addTodo("Learn JavaScript");
addTodo("Build a project");
addTodo("Celebrate!");
// Event listener — react to clicks
const button = document.querySelector("#add-btn");
button.addEventListener("click", () => {
const input = document.querySelector("#todo-input");
if (input.value.trim()) {
addTodo(input.value);
input.value = ""; // clear the input
}
});
// Event delegation — one listener handles all children
list.addEventListener("click", (event) => {
if (event.target.tagName === "LI") {
event.target.classList.toggle("completed");
console.log(`Toggled: ${event.target.textContent}`);
}
});
// Keyboard events
document.addEventListener("keydown", (e) => {
console.log(`Key pressed: ${e.key}`);
if (e.key === "Escape") console.log("Escape pressed!");
});
Output
// (interactive — runs in a browser)
Toggled: Learn JavaScript
Key pressed: Escape
Escape pressed!
Note: Event delegation is like having one receptionist for an entire building instead of one at every office door. When someone walks in, the receptionist checks which office they need and routes them. Add one listener to the parent, check event.target to see which child was clicked — it's faster, uses less memory, and automatically works for new elements added later.

Quick check

What's the difference between textContent and innerHTML?
Array Higher-Order MethodsError Handling