intermediate Step 10 of 20

DOM Manipulation

JavaScript Programming

DOM Manipulation

The Document Object Model (DOM) is a programming interface that represents an HTML document as a tree of objects. Each HTML element becomes a node in this tree, and JavaScript can access and manipulate every part of it — changing text, styles, attributes, and structure dynamically. DOM manipulation is how you make web pages interactive: responding to user actions, updating content without page reloads, showing and hiding elements, and building dynamic user interfaces. This is the core of front-end JavaScript development.

Selecting Elements

// Modern selectors (preferred)
const header = document.querySelector("h1");           // First h1
const allButtons = document.querySelectorAll(".btn");   // All elements with class "btn"
const nav = document.querySelector("#main-nav");        // Element with id "main-nav"
const activeLink = document.querySelector("nav a.active");  // CSS selector

// Legacy selectors (still used)
const byId = document.getElementById("header");
const byClass = document.getElementsByClassName("item");  // Live HTMLCollection
const byTag = document.getElementsByTagName("p");         // Live HTMLCollection

// querySelectorAll returns a static NodeList
allButtons.forEach(btn => {
    console.log(btn.textContent);
});

// Convert NodeList/HTMLCollection to Array for full array methods
const btnArray = [...document.querySelectorAll(".btn")];
const filtered = btnArray.filter(btn => btn.dataset.type === "primary");

Modifying Content and Attributes

const heading = document.querySelector("h1");

// Text content
heading.textContent = "New Heading";          // Sets text (safe — escapes HTML)
heading.innerHTML = "New Heading";   // Sets HTML (careful — XSS risk)

// Attributes
const link = document.querySelector("a");
link.setAttribute("href", "https://example.com");
link.getAttribute("href");
link.removeAttribute("target");
link.hasAttribute("rel");

// Shorthand for common attributes
const img = document.querySelector("img");
img.src = "photo.jpg";
img.alt = "A photo";
img.id = "hero-image";

// Data attributes
const card = document.querySelector(".card");
card.dataset.userId = "123";       // Sets data-user-id="123"
console.log(card.dataset.userId);  // Reads data-user-id

// Classes
const element = document.querySelector(".box");
element.classList.add("active", "highlight");
element.classList.remove("hidden");
element.classList.toggle("dark-mode");
element.classList.contains("active");   // true
element.classList.replace("old", "new");

// Styles
element.style.backgroundColor = "#f0f0f0";
element.style.padding = "20px";
element.style.display = "none";

// Better: toggle classes instead of inline styles
element.classList.add("hidden");  // .hidden { display: none; }

Creating and Inserting Elements

// Create elements
const newDiv = document.createElement("div");
newDiv.className = "card";
newDiv.innerHTML = `
    

New Card

Card content here

`; // Insert into the DOM const container = document.querySelector(".container"); container.appendChild(newDiv); // Add at end container.prepend(newDiv); // Add at beginning container.insertBefore(newDiv, referenceNode); // Insert before specific element // Modern insertion methods container.append(newDiv, "text node"); // Append multiple nodes/text container.before(newDiv); // Insert before container container.after(newDiv); // Insert after container // insertAdjacentHTML — powerful insertion without destroying existing content container.insertAdjacentHTML("beforeend", `

Dynamic Item

Created with insertAdjacentHTML

`); // Positions: "beforebegin", "afterbegin", "beforeend", "afterend" // Remove elements const oldElement = document.querySelector(".old"); oldElement.remove(); // or: oldElement.parentNode.removeChild(oldElement); // Clone elements const clone = newDiv.cloneNode(true); // true = deep clone (with children) container.appendChild(clone);

Building a Dynamic List

// Practical example: render a list of items
function renderUserList(users) {
    const list = document.querySelector("#user-list");
    list.innerHTML = "";  // Clear existing content

    if (users.length === 0) {
        list.innerHTML = '

No users found.

'; return; } const fragment = document.createDocumentFragment(); // Performance optimization users.forEach(user => { const li = document.createElement("li"); li.className = "user-item"; li.dataset.id = user.id; li.innerHTML = ` ${user.name} `; fragment.appendChild(li); }); list.appendChild(fragment); // Single DOM update (better performance) } renderUserList([ { id: 1, name: "Alice", email: "alice@example.com" }, { id: 2, name: "Bob", email: "bob@example.com" } ]);
Pro tip: Minimize direct DOM manipulation for better performance. Batch your changes using DocumentFragment, use classList instead of inline styles, and prefer textContent over innerHTML when you do not need to parse HTML (it is faster and avoids XSS vulnerabilities).

Key Takeaways

  • Use querySelector() and querySelectorAll() with CSS selectors to find elements — they are the modern standard.
  • Modify content with textContent (safe) or innerHTML (parses HTML — watch for XSS).
  • Use classList.add()/remove()/toggle() for CSS classes — avoid manipulating className directly.
  • Create elements with createElement() and insert with append(), prepend(), or insertAdjacentHTML().
  • Use DocumentFragment for batch DOM insertions to minimize reflows and improve performance.