Skip to content

DOM Manipulation

Topic: DOM Manipulation
Concepts Covered: Selecting, modifying, creating, removing elements

The Document Object Model (DOM) is JavaScript’s way of representing and interacting with HTML elements on a webpage. Think of it as a bridge between your JavaScript code and the HTML structure.

  • Every HTML tag becomes an object in JavaScript
  • Nested tags are “children” of their parent elements
  • The entire document is represented as a tree structure
  • JavaScript can modify, add, or remove elements dynamically
<!DOCTYPE html>
<html>
<!-- document.documentElement -->
<head>
<!-- document.head -->
<title>My Page</title>
</head>
<body>
<!-- document.body -->
<h1>Welcome</h1>
<p>Hello World</p>
</body>
</html>

Before you can modify elements, you need to select them from the DOM.

// Select by tag name
const heading = document.querySelector("h1");
// Select by class (first match)
const mainContent = document.querySelector(".main-content");
// Select by ID
const loginForm = document.querySelector("#login-form");
// Select by attribute
const emailInput = document.querySelector('input[type="email"]');
// Complex selectors
const firstListItem = document.querySelector("ul li:first-child");

querySelectorAll() - Select Multiple Elements

Section titled “querySelectorAll() - Select Multiple Elements”
// Select all paragraphs
const allParagraphs = document.querySelectorAll("p");
// Select all elements with a specific class
const cards = document.querySelectorAll(".card");
// Select all input elements
const inputs = document.querySelectorAll("input");
// querySelectorAll returns a NodeList (array-like)
console.log(allParagraphs.length); // Number of paragraphs
// Select by ID (faster than querySelector for IDs)
const element = document.getElementById("my-element");
// Select by class name
const elements = document.getElementsByClassName("my-class");
// Select by tag name
const paragraphs = document.getElementsByTagName("p");
const listItems = document.querySelectorAll("li");
// Loop through NodeList
listItems.forEach(function (item, index) {
console.log(`Item ${index}: ${item.textContent}`);
});
// Convert to array for more methods
const itemsArray = Array.from(listItems);
const itemTexts = itemsArray.map((item) => item.textContent);

Once you’ve selected elements, you can change their content, style, and attributes.

const heading = document.querySelector("h1");
// textContent - plain text only
heading.textContent = "New Heading Text";
// innerHTML - can include HTML tags
const container = document.querySelector(".container");
container.innerHTML = "<p>New paragraph with <strong>bold text</strong></p>";
// Be careful with innerHTML and user input (XSS vulnerability)
const element = document.querySelector(".my-element");
// Individual style properties
element.style.color = "blue";
element.style.backgroundColor = "yellow";
element.style.fontSize = "20px";
element.style.display = "none"; // Hide element
// Multiple styles at once
element.style.cssText = "color: red; font-size: 18px; margin: 10px;";
const element = document.querySelector(".my-element");
// Add class
element.classList.add("active");
element.classList.add("highlight", "visible"); // Add multiple
// Remove class
element.classList.remove("inactive");
// Toggle class (add if not present, remove if present)
element.classList.toggle("hidden");
// Check if class exists
if (element.classList.contains("active")) {
console.log("Element is active");
}
// Replace class
element.classList.replace("old-class", "new-class");
const image = document.querySelector("img");
const link = document.querySelector("a");
// Get attribute
const src = image.getAttribute("src");
const href = link.getAttribute("href");
// Set attribute
image.setAttribute("src", "new-image.jpg");
image.setAttribute("alt", "New image description");
link.setAttribute("href", "https://example.com");
// Remove attribute
image.removeAttribute("title");
// Check if attribute exists
if (image.hasAttribute("data-id")) {
console.log("Image has data-id attribute");
}
// Direct property access (for common attributes)
image.src = "another-image.jpg";
link.href = "https://google.com";
<h1>Welcome</h1>
<p>Hello World</p>
const container = document.querySelector(".container");
const newElement = document.createElement("p");
newElement.textContent = "New paragraph";
// Append to end
container.appendChild(newElement);
// Insert at beginning
container.insertBefore(newElement, container.firstChild);
// Modern methods (newer browsers)
container.append(newElement); // Can append multiple elements
container.prepend(newElement); // Add to beginning
// Insert adjacent to element
const existingElement = document.querySelector("#existing");
existingElement.insertAdjacentHTML("afterend", "<p>After the element</p>");
existingElement.insertAdjacentHTML("beforebegin", "<p>Before the element</p>");
const elementToRemove = document.querySelector(".remove-me");
// Modern way (newer browsers)
elementToRemove.remove();
// Legacy way (older browsers)
elementToRemove.parentNode.removeChild(elementToRemove);
// Remove all children
const container = document.querySelector(".container");
container.innerHTML = ""; // Quick way
// or
while (container.firstChild) {
container.removeChild(container.firstChild);
}
<div class="container">
<div id="task-list">
<!-- Main content goes here -->
</div>
<input type="text" id="task-input">
<button id="add-task">Add</button>
</div>
<div id="gallery-container">
<h2>My Awesome Gallery</h2>
<div id="gallery"></div>
</div>
<form id="registration-form" novalidate>
<h2>Registration</h2>
<div class="form-group">
<label for="name">Name:</label>
<input type="text" id="name" name="name" required minlength="2">
</div>
<div class="form-group">
<label for="email">Email:</label>
<input type="email" id="email" name="email" required>
</div>
<div class="form-group">
<label for="password">Password:</label>
<input type="password" id="password" name="password" required minlength="6">
</div>
<button type="submit">Register</button>
</form>
  1. Cache DOM queries: Store frequently used elements in variables
  2. Use event delegation: For dynamic content, attach events to parent elements
  3. Batch DOM operations: Minimize reflows and repaints
  4. Use document fragments: For multiple element creation
  5. Validate elements exist: Check if querySelector returns null
// ❌ Bad - queries DOM multiple times
document.querySelector("#list").appendChild(item1);
document.querySelector("#list").appendChild(item2);
document.querySelector("#list").appendChild(item3);
// ✅ Good - cache the element
const list = document.querySelector("#list");
list.appendChild(item1);
list.appendChild(item2);
list.appendChild(item3);
// ✅ Even better - use document fragment
const fragment = document.createDocumentFragment();
fragment.appendChild(item1);
fragment.appendChild(item2);
fragment.appendChild(item3);
list.appendChild(fragment);
  1. Modifying DOM during iteration: Can cause elements to be skipped
  2. Memory leaks: Removing elements but keeping references
  3. XSS vulnerabilities: Using innerHTML with user input
  4. Assuming elements exist: Always check if querySelector returns null
  • DOM is your interface to HTML: JavaScript’s way to interact with web pages
  • querySelector/querySelectorAll: Modern, flexible element selection
  • classList: Clean way to manage CSS classes
  • createElement/appendChild: Dynamic content creation
  • Cache DOM queries: Store elements in variables for performance
  • Always validate: Check if elements exist before using them
  1. Create a dynamic table that can add/remove rows
  2. Build a color picker that changes page background
  3. Make a simple drag-and-drop interface
  4. Create a modal dialog system
  5. Build a real-time character counter for a textarea