// JavaScript Fundamentals

The World
of DOM

An interactive deep-dive into the Document Object Model — how browsers represent HTML, and how you control it with JavaScript.

Start Learning →
<html>
<head>
<title>…</title>
</head>
<body>
<header>…</header>
<main>
<p>Hello World</p>
</main>
<footer>…</footer>
</body>
</html>
01
Foundations

What is the DOM?

The DOM is the browser's live, in-memory representation of your HTML page — a tree of objects you can read and change with JavaScript.

Core Concept

When a browser loads an HTML file, it parses the markup and constructs the Document Object Model — a structured, tree-shaped object in memory.


Every element, attribute, and piece of text becomes a Node in this tree. JavaScript can then read and manipulate these nodes, making the page dynamic and interactive.

Document Node Element Tree

Key Facts

  • DOM is a W3C Standard — not a JS feature
  • It is live — changes to HTML reflect instantly
  • Accessed via the global document object
  • Nodes have types: Element, Text, Comment…
  • The root is always document
  • Browsers expose it via JavaScript APIs
// Accessing the document root
console.log(document);
console.log(document.nodeType);   // 9 = Document
console.log(document.nodeName);   // "#document"
console.log(document.URL);        // current page URL
console.log(document.title);      // page title
console.log(document.body);       // <body> element

Node Types

  • 1 — Element Node (e.g. <div>)
  • 2 — Attribute Node
  • 3 — Text Node ("hello")
  • 8 — Comment Node
  • 9 — Document Node
  • 11 — DocumentFragment
Live Playground — Try It runs in this page
// Edit & Run
// Output
// Results appear here…

⚡ Quick Check

Which global object gives you access to the DOM in JavaScript?

A. window.dom
B. document
C. html
D. body
🏅 Unlocked: DOM Explorer
02
Structure

The DOM Tree

Everything in a page lives in a hierarchical tree. Understanding parent, child, and sibling relationships is essential to navigating and manipulating the DOM.

Tree Structure

The DOM forms an upside-down tree: the root (document) is at the top, branching down into <html>, then <head> and <body>, and further into nested elements.


Each node knows its parent, its children, and its siblings.

// Tree relationships
const body = document.body;

// Children
body.children        // HTMLCollection
body.childNodes      // NodeList (incl. text)
body.firstChild      // first node
body.lastChild       // last node
body.firstElementChild

// Parent
body.parentNode      // <html>
body.parentElement

// Siblings
body.previousSibling
body.nextSibling
body.nextElementSibling
▶ Click a node to inspect
📄 document
└─ <html>
├─ <head>
│ └─ <title> "The World of DOM"
└─ <body>
├─ <header>
├─ <main>
│ └─ <p> "Hello World"
└─ <footer>
Click a node above to see its properties →
Live Playground
// Results appear here…

⚡ Quick Check

What property gives you only element children (no text nodes) of a node?

A. childNodes
B. children
C. nodeList
D. elements
🏅 Unlocked: Tree Walker
03
Selection

Selecting Elements

Before you can modify a node, you must find it. JavaScript gives you several powerful methods to target elements by ID, class, tag, or CSS selector.

// Selection methods
// By ID — returns one element
document.getElementById('hero')

// By class — live HTMLCollection
document.getElementsByClassName('lesson')

// By tag — live HTMLCollection
document.getElementsByTagName('p')

// CSS selector — first match
document.querySelector('.lesson h2')

// CSS selector — all matches (static NodeList)
document.querySelectorAll('button[data-type]')

Which to Use?

  • Use getElementById for unique elements
  • Use querySelector for any CSS selector
  • Use querySelectorAll for multiple matches
  • querySelector returns null if not found
  • Can call from any element, not just document
  • Modern code prefers querySelector*

🎮 Selector Game

Type a CSS selector below and see which elements in the sample HTML get highlighted. Try: .card, h4, #intro, [data-type]

Introduction

First paragraph

Second paragraph

Article

A span inside

Last paragraph

Results appear here…
Live Playground
// Results appear here…

⚡ Quick Check

Which method returns a static NodeList of all matching elements?

A. getElementsByClassName()
B. querySelector()
C. querySelectorAll()
D. getElementById()
🏅 Unlocked: CSS Wizard
04
Manipulation

Modifying the DOM

Once you have a reference to a node, you can change its content, attributes, classes, and styles — and the page updates instantly.

// Modifying content
const el = document.querySelector('#demo');

// Text content (safe, no HTML)
el.textContent = 'Hello World';

// HTML content
el.innerHTML = '<strong>Bold text</strong>';

// Attributes
el.setAttribute('data-id', '42');
el.getAttribute('data-id');     // '42'
el.removeAttribute('data-id');

// Classes
el.classList.add('active');
el.classList.remove('hidden');
el.classList.toggle('open');
el.classList.contains('active'); // true

// Inline styles
el.style.color = '#00e5ff';
el.style.backgroundColor = 'black';

textContent vs innerHTML

textContent sets raw text — HTML tags are treated as literal text. It's safe.


innerHTML parses the string as HTML and can inject elements. ⚠ Never use innerHTML with user-supplied data — it opens the door to XSS attacks.

Live Demo

Original text content
Live Playground
// Results appear here…

⚡ Quick Check

Which method adds a CSS class to an element without replacing existing classes?

A. element.class = 'new'
B. element.className = 'new'
C. element.classList.add('new')
D. element.addStyle('new')
🏅 Unlocked: DOM Sculptor
05
Interactivity

DOM Events

Events are how users interact with your page. Learn to listen for clicks, key presses, mouse movements, form submissions — and react to them.

// Event listeners
const btn = document.querySelector('#myBtn');

// Add a listener
btn.addEventListener('click', (event) => {
  console.log('Clicked!', event);
  event.preventDefault(); // stop default action
});

// Remove a listener
function handler(e) { ... }
btn.addEventListener('click', handler);
btn.removeEventListener('click', handler);

// Common events
'click'     'dblclick'   'mouseenter'
'keydown'   'keyup'      'keypress'
'submit'    'change'     'input'
'focus'     'blur'       'scroll'

The Event Object

Every listener receives an Event object with useful properties:


  • event.target — element that triggered it
  • event.type — event name ("click")
  • event.key — for keyboard events
  • event.clientX/Y — mouse coords
  • event.preventDefault() — cancel default
  • event.stopPropagation() — stop bubbling
// Interactive Event Demo
👆 Click, double-click, hover me — events will be logged below
// Event log…

Event Bubbling & Capturing

When an event fires on an element, it bubbles up through all its ancestors. A click on a <span> inside a <div> will also fire the <div>'s click listener.


Use event.stopPropagation() to prevent bubbling, or use event delegation: attach a single listener to a parent element and check event.target.

Live Playground
// Results appear here…

⚡ Quick Check

What does event.stopPropagation() do?

A. Removes the event listener
B. Prevents the default browser action
C. Stops the event from bubbling up the DOM
D. Disables all events on the element
🏅 Unlocked: Event Handler
06
Navigation

Traversal & Relations

Move up, down, and sideways through the DOM tree. Master traversal to navigate any page structure programmatically.

// Traversal API
const el = document.querySelector('#myEl');

// Going UP
el.parentNode
el.parentElement
el.closest('.container') // nearest ancestor matching selector

// Going DOWN
el.children            // element children only
el.childNodes          // all nodes (incl. text)
el.firstElementChild
el.lastElementChild

// Going SIDEWAYS
el.previousElementSibling
el.nextElementSibling

// Useful checks
el.contains(otherEl)   // true if descendant
el.matches('.card')     // true if matches selector

Interactive Traversal

Click a node to select it. Then use the buttons to navigate to relatives.

ul#menu
li.item (first)
li.item (second) span
li.item (third)
Click a node to start…
Live Playground
// Results appear here…

⚡ Quick Check

Which method finds the nearest ancestor matching a CSS selector?

A. parentElement
B. querySelector()
C. closest()
D. parentNode
🏅 Unlocked: Navigator
07
Creation

Creating & Removing Nodes

Build new DOM nodes from scratch and inject them anywhere in the tree — or remove nodes that are no longer needed.

// Creating & inserting
// Create elements
const div = document.createElement('div');
const txt = document.createTextNode('Hello');

div.textContent = 'New element!';
div.className = 'my-class';

// Insert into DOM
parent.appendChild(div);        // at the end
parent.prepend(div);            // at the start
parent.insertBefore(div, ref);  // before ref
ref.after(div);                 // after ref
ref.before(div);                // before ref

// Modern: insertAdjacentHTML
el.insertAdjacentHTML('beforeend', '<p>Hi</p>');

// Removing
el.remove();                    // remove self
parent.removeChild(child);      // remove child
el.replaceWith(newEl);          // replace

// Cloning
el.cloneNode(true);            // deep clone

DocumentFragment

When inserting many elements, use a DocumentFragment — a lightweight container that lives outside the DOM. Build your structure in the fragment, then insert it all at once. This causes only one reflow instead of many.


const frag = document.createDocumentFragment();
for (let i = 0; i < 100; i++) {
  const li = document.createElement('li');
  li.textContent = `Item ${i}`;
  frag.appendChild(li);
}
list.appendChild(frag); // one DOM update

Live Demo

Live Playground
// Results appear here…

⚡ Quick Check

Which method removes an element from the DOM without needing a reference to its parent?

A. parent.removeChild(el)
B. el.remove()
C. document.delete(el)
D. el.destroy()
🏅 Unlocked: Node Builder
08
Final Challenge

Build a Mini Todo App

Apply everything you've learned — selection, modification, creation, events — to build a working todo list from scratch in the playground below.

🎯 Your Mission

  • Read the input value when the button is clicked
  • Create a new <div> with the todo text
  • Add a delete button inside each todo
  • Append the todo to the list container
  • Bonus: toggle a "done" class on click
Final Challenge Playground
// Your code
// Console
// Console output…
// Live App

⚡ Final Quiz

Which approach is most performant when inserting 1000 list items into the DOM?

A. Call appendChild 1000 times in a loop
B. Append all items to a DocumentFragment, then insert once
C. Set innerHTML to a large HTML string
D. Use createElement 1000 times without appending
🏅 Unlocked: DOM Master