AlgoDaily

DOM Manipulation

Read at your own pace. Code execution, quizzes, progress tracking, and the AI tutor are available in the interactive view with JavaScript enabled.

From Values To Views

Why DOM manipulation matters

In Learning JavaScript Basics, you worked with values, bindings, functions, scope, and comparison rules. Now we’ll apply those tools to the thing frontend engineers are ultimately paid to shape: the page the user sees and touches.

The DOM — Document Object Model — is the browser’s structured representation of HTML. DOM manipulation is how JavaScript can:

  • read what is currently on the page
  • create, remove, or reorder interface pieces
  • respond to clicks, typing, and other user actions
  • keep UI state and visible UI in sync

Even if you mostly work in React, Vue, Svelte, or another framework, staff-level frontend interviews often probe whether you understand the browser underneath the abstraction. Frameworks are not magic; they eventually update the DOM too.

Think of this lesson as learning how to move pieces on the game board directly before we later talk about getting remote data with AJAX and Fetch API.

From Values To Views

The DOM Tree

The page is a tree

HTML text is parsed by the browser into a tree of objects called nodes. Elements, text, comments, and the document itself are all nodes.

A small page like this:

<main>
  <h1>Reading List</h1>
  <ul>
    <li>Dune</li>
    <li>Neuromancer</li>
  </ul>
</main>

becomes a shape like:

document
└── html
    └── body
        └── main
            ├── h1
            │   └── "Reading List"
            └── ul
                ├── li → "Dune"
                └── li → "Neuromancer"

Important mental model: you are not editing an HTML string most of the time. You are working with live objects representing page nodes.

That distinction matters because DOM objects have properties, methods, parent/child relationships, and event behavior.

The DOM Tree

Finding Page Elements

Query first, then act

Most DOM work starts by selecting an element or a group of elements.

Common tools:

  • document.querySelector(selector) returns the first matching element or null
  • document.querySelectorAll(selector) returns a static list of all matches
  • element.querySelector(...) searches inside one subtree

Use CSS selector syntax, but do not turn this into a CSS lesson yet. For now, focus on the API shape: find the node, then inspect or change it.

Here’s a standalone browser-console example using a tiny action-movie watchlist.

```javascript
document.body.innerHTML = `
  <main id="app">
    <h1>Action Movie Night</h1>
    <ul class="watchlist">
      <li data-rating="5">Mad Max: Fury Road</li>
      <li data-rating="4">John Wick</li>
      <li data-rating="3">Speed</li>
    </ul>
  </main>
`;

const title = document.querySelector("h1");
const movies = document.querySelectorAll(".watchlist li");
const topPick = document.querySelector('[data-rating="5"]');

console.log(title.textContent);
console.log(movies.length);
console.log(topPick.textContent);
```

Selector Result Check

Given this DOM:

<section id="games">
  <button class="choice">Puzzle</button>
  <button class="choice featured">RPG</button>
</section>

What does document.querySelector(".choice") return?

Changing Nodes Safely

Text, attributes, and structure

Once you have a DOM node, you can update what the user sees.

Useful properties and methods:

  • textContent changes text safely
  • setAttribute(name, value) sets an attribute
  • classList.add/remove/toggle(...) changes class tokens
  • append(...) inserts nodes or text at the end
  • remove() deletes a node

Prefer textContent when inserting plain text. It treats content as text, not HTML, which is safer and usually clearer.

Below, we build a tiny reading queue and log the final visible result.

```javascript
document.body.innerHTML = `
  <section id="library">
    <h1>Reading Queue</h1>
    <ul id="books"></ul>
  </section>
`;

const books = document.querySelector("#books");

const item = document.createElement("li");
item.textContent = "The Long Way to a Small, Angry Planet";
item.setAttribute("data-status", "next-up");
item.classList.add("book", "priority");

books.append(item);

console.log(books.children.length);
console.log(books.firstElementChild.textContent);
console.log(books.firstElementChild.getAttribute("data-status"));
```

HTML Injection Swipe

True or false: if a value comes from a user, it is always safe to insert it into the page with element.innerHTML = value.

Events Wire Interaction

DOM changes become useful with events

A static DOM update is like placing pieces on a puzzle board. Events let the user move them.

The core pattern:

  1. Select or create an element
  2. Attach an event listener
  3. In the handler, read state and update the DOM

For many repeated elements, use event delegation: attach one listener to a parent and inspect where the event came from. This avoids wiring dozens of individual listeners and handles future child elements naturally.

This example uses one listener for multiple reality-show elimination buttons.

```javascript
document.body.innerHTML = `
  <section id="show">
    <h1>Elimination Board</h1>
    <button data-contestant="Ava">Eliminate Ava</button>
    <button data-contestant="Milo">Eliminate Milo</button>
    <p id="result">No one eliminated yet.</p>
  </section>
`;

const show = document.querySelector("#show");
const result = document.querySelector("#result");

show.addEventListener("click", function handleClick(event) {
  const button = event.target.closest("button[data-contestant]");

  if (!button) return;

  result.textContent = `${button.dataset.contestant} has left the villa.`;
  console.log(result.textContent);
});

// Simulate a user click so this standalone example prints output.
document.querySelector('[data-contestant="Milo"]').click();
```

Listener Method Blank

Fill in the blank with the DOM method name:

element.________("click", handler)

Mutation Cost Matters

DOM work has a cost

DOM manipulation is powerful, but it is not free. The browser may need to recalculate layout, repaint pixels, or rebuild accessibility information after changes.

For small interfaces, this usually does not matter. For staff-level frontend work, you should know the shape of efficient mutation patterns.

Prefer:

  • Batch changes: build several nodes, then attach them together
  • Minimize layout thrashing: avoid alternating reads like offsetHeight with writes like changing classes in tight loops
  • Use stable parent containers: update the smallest subtree you can
  • Keep state separate from DOM when complexity grows: let DOM reflect state rather than becoming your only source of truth

A helpful rule: make the browser do fewer big, predictable updates instead of many tiny surprising ones.

This is one reason frameworks exist, but the underlying browser cost model still matters when debugging janky UIs, long tasks, or slow interaction response.

Mutation Cost Matters

DOM Mastery Checklist

What you should carry forward

You now have the browser-level tools to turn JavaScript values into visible, interactive UI.

Before moving on, make sure you can explain and use:

  • The DOM as a tree of live objects, not just an HTML string
  • querySelector vs querySelectorAll
  • Creating elements with document.createElement
  • Updating text with textContent
  • Setting attributes and classes intentionally
  • Adding event listeners with addEventListener
  • Using event delegation for repeated interactive children
  • Avoiding unsafe innerHTML for untrusted text
  • Thinking about performance when doing many mutations

This lesson sits directly after Learning JavaScript Basics because DOM APIs rely on the same fundamentals: values, functions, scope, and equality checks. Next, AJAX and Fetch API will add remote data to the picture; DOM manipulation is how that data eventually becomes UI.

DOM Mastery Checklist

Open interactive view →