JavaScript DOM Manipulation: A Complete Guide
The Document Object Model (DOM) is JavaScript’s interface to HTML. It lets you read, modify, and respond to user interactions.
Selecting Elements
// Single element (returns first match)
const header = document.getElementById("header");
const button = document.querySelector(".btn-primary");
// Multiple elements
const buttons = document.querySelectorAll(".btn");
const items = document.getElementsByClassName("item");
const divs = document.getElementsByTagName("div");Modifying Content
const title = document.querySelector("h1");
// Text content (safe, no HTML parsing)
title.textContent = "New Title";
// HTML content (use with caution — XSS risk)
title.innerHTML = "<span>New Title</span>";Modifying Attributes
const img = document.querySelector("img");
// Get/set attributes
img.getAttribute("src"); // "image.jpg"
img.setAttribute("alt", "Description");
img.hasAttribute("src"); // true
img.removeAttribute("title");
// Direct property access (for standard attributes)
img.src = "new-image.jpg";
img.alt = "New description";Modifying Classes
const element = document.querySelector(".card");
element.classList.add("active");
element.classList.remove("hidden");
element.classList.toggle("expanded");
element.classList.contains("active"); // true/false
// Replace (add/remove in one call)
element.classList.replace("old-class", "new-class");Modifying Styles
const box = document.querySelector(".box");
// Inline styles (camelCase property names)
box.style.backgroundColor = "blue";
box.style.fontSize = "16px";
box.style.display = "flex";
// Better: toggle classes instead
box.classList.add("highlight");Creating and Removing Elements
// Create
const newDiv = document.createElement("div");
newDiv.textContent = "Hello";
newDiv.classList.add("card");
// Insert
document.body.appendChild(newDiv);
container.insertBefore(newDiv, referenceElement);
container.insertAdjacentHTML("beforeend", "<p>New</p>");
// Remove
element.remove(); // modern
element.parentNode.removeChild(element); // legacy
// Clone
const clone = element.cloneNode(true); // deep clone
Event Handling
// Add event listener
button.addEventListener("click", function(event) {
console.log("Button clicked!");
console.log(event.target); // the clicked element
console.log(event.type); // "click"
});
// Arrow function
button.addEventListener("click", (e) => {
console.log("Clicked");
});
// Remove listener
button.removeEventListener("click", handler);
// Once — fires only once
button.addEventListener("click", handler, { once: true });Common Events
// Mouse
element.addEventListener("click", handler);
element.addEventListener("dblclick", handler);
element.addEventListener("mouseenter", handler);
element.addEventListener("mouseleave", handler);
// Keyboard
document.addEventListener("keydown", (e) => {
if (e.key === "Enter") submit();
if (e.key === "Escape") close();
});
// Form
form.addEventListener("submit", (e) => {
e.preventDefault(); // don't reload the page
submitForm();
});
input.addEventListener("input", handler); // every keystroke
input.addEventListener("change", handler); // when focus lost
// Window
window.addEventListener("load", handler);
window.addEventListener("resize", handler);
window.addEventListener("scroll", handler);Event Delegation
Instead of adding listeners to many elements, add one to the parent:
// Instead of:
document.querySelectorAll(".item").forEach(item => {
item.addEventListener("click", handler);
});
// Do this (works for dynamically added items too):
document.querySelector(".list").addEventListener("click", (e) => {
if (e.target.matches(".item")) {
handleItemClick(e.target);
}
});Traversing the DOM
const element = document.querySelector(".card");
// Parent
element.parentElement;
element.closest(".container"); // nearest ancestor matching selector
// Children
element.children; // HTMLCollection (live)
element.querySelector(".child"); // first matching child
// Siblings
element.nextElementSibling;
element.previousElementSibling;Form Values
const input = document.querySelector("#email");
const checkbox = document.querySelector("#agree");
const select = document.querySelector("#country");
input.value; // current text
checkbox.checked; // true/false
select.value; // selected option value
// FormData (for entire forms)
const form = document.querySelector("form");
const data = new FormData(form);
const email = data.get("email");Practical Patterns
Toggle Menu
const menu = document.querySelector(".menu");
const toggle = document.querySelector(".menu-toggle");
toggle.addEventListener("click", () => {
menu.classList.toggle("open");
});Fetch and Display Data
async function loadUsers() {
const response = await fetch("/api/users");
const users = await response.json();
const list = document.querySelector(".user-list");
list.innerHTML = users.map(user => `
<li class="user-card">
<h3>${user.name}</h3>
<p>${user.email}</p>
</li>
`).join("");
}Debounced Search
let timeout;
searchInput.addEventListener("input", () => {
clearTimeout(timeout);
timeout = setTimeout(() => {
performSearch(searchInput.value);
}, 300); // wait 300ms after last keystroke
});Related: Learn CSS Grid and responsive design.