Kazi Rahamatullah
Kazi Rahamatullah
AboutProjectsBlogContact
UsesBooks
ResumeView CV
Kazi Rahamatullah

© Copyright 2026 Kazi Rahamatullah

AboutProjectsBlogBooksUses
Twitter/XGitHubProduct HuntCodeSandbox
Back to Blog
HTMLDOMJavaScriptWeb DevelopmentFrontend Development

Mastering the DOM Manipulation

Complete DOM guide — tree structure, selection APIs, manipulation, events, traversal, delegation, and interactive playgrounds with real-world examples.

Jul 3, 20269 min read
Mastering the DOM Manipulation

Introduction

The Document Object Model (DOM) is the browser's logical representation of your HTML — a tree of nodes you can read and change with JavaScript. Every dynamic UI, form validation flow, and interactive component ultimately comes down to DOM selection, manipulation, and events.

This guide walks topic-by-topic through mastering the DOM:

  1. Introduction & basics — window, document, node tree
  2. DOM selection — IDs, classes, tags, querySelector
  3. DOM manipulation — content, styles, attributes, creating nodes
  4. DOM events — listeners, event types, bubbling, delegation
  5. Advanced topics — traversal, fragments, Shadow DOM
  6. Practice projects — todo list, validation, gallery, nav

Course Reference

Quick index

#Section
1Introduction to the DOM
2Basics — window & document
↳ DOM tree explorer
3DOM selection
↳ Selection playground
4DOM manipulation
↳ Manipulation lab
5DOM events
↳ Events playground
6Traversal & advanced topics
7DOM practice ideas

1. Introduction to the DOM

When a browser loads HTML, it builds an in-memory tree. Each tag, attribute, and text node becomes an object you can access from JavaScript.

ConceptMeaning
DocumentThe entire web page as a node tree
NodeAny point in the tree (element, text, comment)
ElementA node with a tag name (div, p, button)
PurposeDynamic interaction — update UI without full page reload
html
<!DOCTYPE html>
<html>
  <head>
    <title>My App</title>
  </head>
  <body>
    <h1 id="title">Hello</h1>
    <button id="btn">Click</button>
  </body>
</html>
javascript
const title = document.getElementById('title')
title.textContent = 'Hello, DOM!'

Note

The DOM is an API — not the HTML source file itself. JavaScript changes the live tree; element.innerHTML in DevTools reflects those updates immediately.

Interview Answer

The DOM is a platform-independent representation of HTML/XML as a tree of nodes. JavaScript uses the DOM API to query, create, modify, and remove nodes — enabling dynamic web pages without server round-trips for every UI change.

Back to index


2. Basics — window & document

Window object

The window is the global object in browsers — tabs, viewport, timers, and document all hang off it.

javascript
console.log(window.innerWidth)
window.addEventListener('resize', () => console.log('resized'))
const id = window.setTimeout(() => {}, 1000)
window.clearTimeout(id)

Document object

document is the entry point to the DOM tree.

javascript
document.documentElement // <html>
document.head // <head>
document.body // <body>
document.title // page title string

Tree structure

RelationshipAPI examples
Parentnode.parentNode, node.parentElement
Childrennode.children, node.childNodes
Siblingsnode.nextElementSibling, previousElementSibling
javascript
const card = document.querySelector('.card')
const parent = card.parentElement
const next = card.nextElementSibling

Interactive: DOM tree explorer

DOM Tree Explorer

Click nodes in the document tree — see parent/child relationships and how HTML becomes a node hierarchy.

Document tree

Selected node

<div.card>

nodeType: Element

Relationship: Child of main

document.documentElement → <html>

document.body → <body>

document.head → <head>

Back to index


3. DOM selection

Choosing the right API keeps code readable and performant.

APIReturnsBest for
getElementById(id)Single element / nullOne unique element
getElementsByClassNameLive HTMLCollectionAll elements with a class
getElementsByTagNameLive HTMLCollectionAll elements with a tag
querySelector(selector)First match / nullFlexible CSS selector (one)
querySelectorAll(selector)Static NodeListFlexible CSS selector (all)
javascript
const hero = document.getElementById('hero')
const cards = document.getElementsByClassName('card')
const paragraphs = document.getElementsByTagName('p')
const firstBtn = document.querySelector('button.primary')
const allBtns = document.querySelectorAll('button')
javascript
// Scoped selection — search inside a container
const nav = document.querySelector('nav')
const links = nav.querySelectorAll('a[href^="/blog"]')

Tip

querySelector / querySelectorAll accept any valid CSS selector — pseudo-classes, attribute selectors, and combinators. Scope queries to a parent element to avoid scanning the entire document.

Interactive: selection playground

DOM Selection Playground

Compare selection APIs — single element, live collections, and CSS selector queries.

document.querySelector('.heading.muted')

<h1 id="title">

class: heading

Hello DOM

<h2 id="subtitle">

class: heading muted

Selection APIs

<div id="card">

class: card

Card content

<button id="cta">

class: card primary

Get started

Matched 1 element: subtitle

Prefer querySelector / querySelectorAll for flexible CSS selectors. Use IDs when you need exactly one known element.

Back to index


4. DOM manipulation

Content

PropertyBehavior
textContentPlain text only — safe for user-facing strings
innerTextRendered text (CSS-aware, reflows)
innerHTMLParses HTML markup — XSS risk with user input
javascript
const msg = document.querySelector('#status')
msg.textContent = 'Saved successfully'
 
// Dangerous with untrusted input:
// el.innerHTML = userInput

Styling & classes

javascript
const box = document.querySelector('.box')
box.style.backgroundColor = 'cyan'
box.className = 'box active'
box.classList.add('highlight')
box.classList.remove('hidden')
box.classList.toggle('open')
box.classList.contains('open') // true/false

Creating & inserting nodes

javascript
const list = document.querySelector('#todo-list')
const li = document.createElement('li')
li.textContent = 'Learn DOM manipulation'
li.setAttribute('data-id', '1')
 
list.appendChild(li) // add at end
list.insertBefore(li, list.firstChild) // add at start
li.remove() // modern removal

Attributes

javascript
const input = document.querySelector('input')
input.setAttribute('aria-label', 'Email address')
input.getAttribute('type') // 'email'
input.removeAttribute('disabled')
input.dataset.userId = '42' // data-user-id="42"

Warning

Prefer textContent over innerHTML when displaying user-generated content. If you must render HTML, sanitize it first.

Interactive: manipulation lab

DOM Manipulation Lab

Practice content updates, classList toggles, and creating elements — the core building blocks of dynamic UIs.

el.textContent = '...'

el.classList.toggle('active')

const li = document.createElement('li')

parent.appendChild(li)

Live card

Edit me with JavaScript

  • Learn selection
  • Manipulate content

Use textContent for safe text updates. Reserve innerHTML for trusted markup only — it parses HTML and can introduce XSS if fed user input.

Back to index


5. DOM events

Adding listeners

javascript
const btn = document.querySelector('#save')
 
function handleSave(event) {
  console.log(event.type) // 'click'
  console.log(event.target) // element that triggered the event
}
 
btn.addEventListener('click', handleSave)
btn.removeEventListener('click', handleSave)

Common event types

CategoryEvents
Mouseclick, dblclick, mouseenter
Keyboardkeydown, keyup, keypress
Formsubmit, input, change
Windowload, resize, scroll
javascript
form.addEventListener('submit', (e) => {
  e.preventDefault() // block default form navigation
  const data = new FormData(form)
  save(data)
})
 
input.addEventListener('input', (e) => {
  validate(e.target.value)
})

Event object essentials

javascript
link.addEventListener('click', (event) => {
  event.preventDefault() // cancel default action
  event.stopPropagation() // stop bubbling to parents
  console.log(event.currentTarget) // element listener is on
  console.log(event.target) // deepest clicked element
})

Event bubbling & delegation

Events propagate from target → ancestors (bubble phase). Attach one listener on a parent to handle many children:

javascript
const list = document.querySelector('#task-list')
 
list.addEventListener('click', (e) => {
  const item = e.target.closest('[data-task-id]')
  if (!item) return
  toggleTask(item.dataset.taskId)
})

Interactive: events playground

DOM Events Playground

See event bubbling on nested elements and efficient delegation on a dynamic list.

grandparent (click me)

parent — stopPropagation

child target

Event log (bubble phase)

Click nested boxes…

Interview Answer

Event bubbling means an event fires on the target then travels up the DOM tree. Event delegation attaches a single listener on a parent and uses event.target (or closest) to handle child interactions — ideal for dynamic lists and better memory usage.

Back to index


6. Traversal & advanced topics

Traversing the DOM

javascript
const node = document.querySelector('.item')
node.parentElement
node.children
node.firstElementChild
node.lastElementChild
node.nextElementSibling
node.previousElementSibling

DocumentFragment — batch DOM updates

javascript
const fragment = document.createDocumentFragment()
const items = ['Apple', 'Banana', 'Cherry']
 
items.forEach((fruit) => {
  const li = document.createElement('li')
  li.textContent = fruit
  fragment.appendChild(li)
})
 
list.appendChild(fragment) // single reflow

Performance

Appending many nodes inside a DocumentFragment then inserting once reduces layout thrashing compared to repeated appendChild calls on the live document.

Shadow DOM & Web Components (overview)

Shadow DOM encapsulates markup and styles inside a component boundary. Web Components (customElements.define) let you build reusable HTML tags.

javascript
class GreetingCard extends HTMLElement {
  connectedCallback() {
    const shadow = this.attachShadow({ mode: 'open' })
    shadow.innerHTML = `
      <style>p { color: teal; font-weight: bold; }</style>
      <p>Hello from Shadow DOM</p>
    `
  }
}
 
customElements.define('greeting-card', GreetingCard)
html
<greeting-card></greeting-card>

Note

React, Vue, and Svelte abstract most raw DOM work — but they still render to the DOM under the hood. Understanding selection, events, and delegation makes debugging and vanilla integrations easier.

Back to index


7. DOM practice ideas

Build these projects to cement the APIs:

Todo list

javascript
const form = document.querySelector('#todo-form')
const list = document.querySelector('#todo-list')
 
form.addEventListener('submit', (e) => {
  e.preventDefault()
  const input = form.querySelector('input')
  const li = document.createElement('li')
  li.textContent = input.value
  list.appendChild(li)
  input.value = ''
})
 
list.addEventListener('click', (e) => {
  if (e.target.matches('li')) e.target.classList.toggle('done')
})

Real-time form validation

javascript
const email = document.querySelector('#email')
const hint = document.querySelector('#email-hint')
 
email.addEventListener('input', () => {
  const valid = email.validity.valid
  hint.textContent = valid ? '' : 'Enter a valid email'
  email.classList.toggle('invalid', !valid)
})

Dynamic image gallery

javascript
const gallery = document.querySelector('#gallery')
const images = ['/a.jpg', '/b.jpg', '/c.jpg']
 
images.forEach((src) => {
  const img = document.createElement('img')
  img.src = src
  img.alt = 'Gallery item'
  img.addEventListener('click', () => openLightbox(src))
  gallery.appendChild(img)
})

Interactive navigation menu

javascript
const toggle = document.querySelector('.nav-toggle')
const menu = document.querySelector('.nav-menu')
 
toggle.addEventListener('click', () => {
  menu.classList.toggle('open')
  toggle.setAttribute('aria-expanded', menu.classList.contains('open'))
})

Tip

Start vanilla DOM before reaching for frameworks. You'll recognize what React's useRef, event handlers, and portals are solving when you've built the same patterns by hand.

Back to index


Conclusion

The DOM is the bridge between your HTML and JavaScript. Master the tree mental model, pick the right selection API, manipulate safely, and handle events with bubbling and delegation.

Key takeaways:

  • DOM = live tree of nodes representing the document
  • document / window are your entry points in the browser
  • querySelector(All) for flexible selection; scope to parents when possible
  • textContent and classList cover most day-to-day updates
  • addEventListener + delegation scale to dynamic UIs
  • DocumentFragment batches inserts; Shadow DOM encapsulates components

From todo lists to full SPAs — it all starts with the DOM.


Have questions about DOM APIs or events? Reach out via the contact page.

Share this article

XLinkedInFacebook
Kazi Rahamatullah

Written by

Kazi Rahamatullah

FullStack Developer

X / TwitterGitHubLinkedIn

Subscribe to my newsletter

Stay up to date and get notified when I share new contents.

No spam ever, unsubscribe anytime