⚡ Phase 1 · Foundations 🟡 Intermediate MODULE 10

DOM Manipulation

⏱️ 40 min read
📖 Theory + Code
🧩 5 Quiz Questions
🏗️ 1 Challenge
Your progress in Phase 177%
🎯 What you'll learn: The Document Object Model (DOM) is the bridge between JavaScript and HTML. You'll learn to select elements, change content and styles, create and remove elements, traverse the DOM tree, and build interactive pages.

What is the DOM?

When a browser loads an HTML page, it creates a tree of objects representing the page structure. This tree is called the Document Object Model (DOM). JavaScript can read and modify this tree to dynamically change the page.

🌳
The DOM is a tree structure
Every HTML tag becomes a node in the DOM tree. The document object is the root. From there: document.html → document.body → div → p → text. JavaScript traverses this tree to find and modify elements.

Selecting Elements

DOM Selection Methods
JS
// getElementById — fastest, by unique ID
const header = document.getElementById('main-header');

// querySelector — CSS selector, returns FIRST match
const btn = document.querySelector('.btn-primary');
const first = document.querySelector('ul li');
const byId = document.querySelector('#hero');

// querySelectorAll — returns NodeList of ALL matches
const allBtns = document.querySelectorAll('button');
const items = document.querySelectorAll('.list-item');

// Convert NodeList to array (for full array methods)
const btnsArr = [...allBtns];
const btnsArr2 = Array.from(allBtns);

// Iterate over NodeList
items.forEach(item => item.classList.add('visible'));

Changing Content & Styles

innerHTML, textContent, style, classList
JS
const box = document.querySelector('#myBox');

// innerHTML — parses HTML tags (use carefully!)
box.innerHTML = '<strong>Hello</strong> World';

// textContent — plain text only (safer)
box.textContent = 'Hello World';

// innerText — visible text (respects CSS)
box.innerText = 'Visible text';

// Inline styles
box.style.color = 'red';
box.style.backgroundColor = '#1a1a2e';
box.style.fontSize = '20px';

// classList — manage CSS classes
box.classList.add('active');          // add class
box.classList.remove('hidden');       // remove class
box.classList.toggle('dark');         // add if absent, remove if present
box.classList.contains('active');     // true/false
box.classList.replace('old', 'new');  // swap classes

// Attributes
box.setAttribute('data-id', '42');
box.getAttribute('data-id');           // '42'
box.removeAttribute('data-id');
⚠️
XSS Warning with innerHTML
Never set innerHTML with untrusted user input — it can execute malicious scripts (XSS attack). Use textContent for user data, and innerHTML only for trusted HTML strings.

Creating & Removing Elements

createElement, appendChild, remove
JS
// Create a new element
const li = document.createElement('li');
li.textContent = 'New Item';
li.classList.add('list-item');

// Append to parent (at the end)
const ul = document.querySelector('#myList');
ul.appendChild(li);

// insertBefore(newNode, referenceNode)
const firstLi = ul.querySelector('li');
ul.insertBefore(li, firstLi);  // insert before first

// Modern: insertAdjacentHTML (fast & flexible)
ul.insertAdjacentHTML('beforeend', '<li>Last Item</li>');
ul.insertAdjacentHTML('afterbegin', '<li>First Item</li>');

// Remove an element
li.remove();               // modern, removes itself
ul.removeChild(li);       // older way

// Clone an element
const clone = li.cloneNode(true);  // deep clone (with children)

Traversal & DOMContentLoaded

DOM Traversal & DOMContentLoaded
JS
const el = document.querySelector('.item');

// Parent / Children
el.parentNode;           // immediate parent (any node)
el.parentElement;        // immediate parent (element only)
el.children;             // HTMLCollection of children
el.firstElementChild;    // first child element
el.lastElementChild;     // last child element

// Siblings
el.nextElementSibling;   // next element
el.previousElementSibling; // previous element

// Count children
el.childElementCount;    // number of child elements

// DOMContentLoaded — runs when HTML is parsed (not all assets)
document.addEventListener('DOMContentLoaded', () => {
  // Safe to access DOM elements here
  const app = document.getElementById('app');
  initApp();
});

// Alternatively, place script before </body>
// or use defer attribute on script tag

Practical Examples

Toggle Dark Mode
JS
// Toggle dark mode on button click
const toggleBtn = document.getElementById('darkToggle');

toggleBtn.addEventListener('click', () => {
  document.body.classList.toggle('dark-mode');
  const isDark = document.body.classList.contains('dark-mode');
  toggleBtn.textContent = isDark ? '☀️ Light Mode' : '🌙 Dark Mode';
  // Save preference
  localStorage.setItem('darkMode', isDark);
});

// Load saved preference
if (localStorage.getItem('darkMode') === 'true') {
  document.body.classList.add('dark-mode');
}

// Dynamic list rendering
function renderList(items, containerId) {
  const container = document.getElementById(containerId);
  container.innerHTML = items.map(item =>
    `<li class="item" data-id="${item.id}">${item.name}</li>`
  ).join('');
}
🧩 Knowledge Check — DOM
5 questions about DOM manipulation.
1. What does document.querySelector('.item') return?
2. What is the difference between textContent and innerHTML?
3. Which method adds a CSS class to an element?
4. What event fires when the HTML is parsed and DOM is ready (before images load)?
5. How do you access the next sibling element of an element?
Challenge — Dynamic To-Do List
Build a fully working to-do app using DOM manipulation · Intermediate
Build a Dynamic To-Do List

Create todo.html with HTML + JS:

1. Text input + "Add" button at the top
2. addTask(text) — creates an <li> element with the task text and a delete button
3. Each task has a checkbox — checking it adds "completed" class (line-through style)
4. Delete button calls item.remove()
5. Show task count: "3 tasks remaining"
6. Empty state: show "No tasks yet" message when list is empty
7. Press Enter in input to add task
💡 Show hints
  • Use document.createElement('li') then set innerHTML for the task + button
  • Use insertAdjacentHTML('beforeend', ...) for fast insertion
  • For the count: document.querySelectorAll('li:not(.completed)').length
  • Listen for keydown event with e.key === 'Enter'
Finished this lesson?
Mark it complete to track your progress.
🎉

Lesson 10 Complete!

DOM mastered! You can now manipulate web pages with JavaScript. Next: Events!

Module 10 of 13Phase 1 — JS Foundations