Skip to main content
๐ŸŒbeginner

DOM Manipulation

The DOM (Document Object Model) is JavaScript's interface to the HTML page. Learn to select, create, modify, and remove elements programmatically.

What is the DOM?

When the browser loads an HTML page, it creates a tree of objects called the Document Object Model (DOM). Every HTML element becomes a Node in this tree that JavaScript can read and modify.

hljs html
<html>
  <body>
    <h1 id="title">Hello</h1>
    <ul class="list">
      <li>Item 1</li>
      <li>Item 2</li>
    </ul>
  </body>
</html>

JavaScript can access and change every part of this tree.

Selecting Elements

hljs javascript
// By ID (returns single element or null)
const title = document.getElementById("title");

// By CSS selector โ€” single element
const first = document.querySelector(".list li");     // first match
const btn = document.querySelector("#submit-btn");

// By CSS selector โ€” all matches (NodeList)
const allItems = document.querySelectorAll(".list li");
const allBtns = document.querySelectorAll("button");

// Convert NodeList to Array for array methods
const itemsArray = Array.from(allItems);
// or: [...allItems]

// Older methods (still work)
document.getElementsByClassName("list"); // HTMLCollection
document.getElementsByTagName("li");     // HTMLCollection

Reading and Modifying Content

hljs javascript
const el = document.querySelector("#title");

// Text content (safe โ€” no HTML parsing)
el.textContent;          // get
el.textContent = "New Title"; // set

// HTML content (careful with user input โ€” XSS risk!)
el.innerHTML;            // get
el.innerHTML = "<strong>Bold Title</strong>"; // set

// Form input values
const input = document.querySelector("input");
input.value;             // current value
input.value = "default"; // set value

โš ๏ธNever use innerHTML with user input

innerHTML parses the string as HTML. If you set it to user-provided content, you risk XSS (Cross-Site Scripting) attacks. Always use textContent for user data, or sanitize the HTML first.

Modifying Attributes and Classes

hljs javascript
const img = document.querySelector("img");

// Attributes
img.getAttribute("src");              // get
img.setAttribute("src", "/new.png");  // set
img.removeAttribute("alt");           // remove
img.hasAttribute("data-id");          // check

// Direct property (faster than getAttribute/setAttribute for standard attrs)
img.src = "/new.png";
img.alt = "Description";
img.disabled = true;    // form elements
img.href = "...";       // links

// Classes
el.classList.add("active");
el.classList.remove("hidden");
el.classList.toggle("open");          // add if absent, remove if present
el.classList.contains("active");      // true/false
el.classList.replace("old", "new");

// All classes as a string
el.className; // "class1 class2 class3"

Modifying Styles

hljs javascript
const box = document.querySelector(".box");

// Inline styles
box.style.color = "red";
box.style.backgroundColor = "#1e293b"; // camelCase!
box.style.fontSize = "16px";
box.style.display = "none"; // hide
box.style.display = "";     // remove inline style (revert to CSS)

// Read computed style (what's actually applied, including CSS)
const computed = getComputedStyle(box);
console.log(computed.color);      // "rgb(255, 0, 0)"
console.log(computed.fontSize);   // "16px"

Creating and Inserting Elements

hljs javascript
// Create element
const newItem = document.createElement("li");
newItem.textContent = "New item";
newItem.classList.add("list-item");

// Insert
const list = document.querySelector("ul");

list.appendChild(newItem);      // add at end
list.prepend(newItem);          // add at start
list.insertBefore(newItem, list.firstChild); // before specific child

// Modern: insertAdjacentElement
list.insertAdjacentElement("beforeend", newItem);   // inside, at end
list.insertAdjacentElement("afterbegin", newItem);  // inside, at start
list.insertAdjacentElement("beforebegin", newItem); // before the element
list.insertAdjacentElement("afterend", newItem);    // after the element

// Insert HTML string
list.insertAdjacentHTML("beforeend", "<li>HTML item</li>");

// Create fragment (efficient for multiple insertions)
const fragment = document.createDocumentFragment();
["a", "b", "c"].forEach(text => {
  const li = document.createElement("li");
  li.textContent = text;
  fragment.appendChild(li);
});
list.appendChild(fragment); // single DOM update

Removing Elements

hljs javascript
const el = document.querySelector("#to-remove");

// Modern
el.remove();

// Older (still works)
el.parentNode.removeChild(el);

Traversing the DOM

hljs javascript
const child = document.querySelector(".child");

// Parent
child.parentElement;      // parent element (null if none)
child.parentNode;         // parent node (could be document)

// Children
child.children;           // HTMLCollection of child elements
child.childNodes;         // NodeList of all child nodes (includes text nodes)
child.firstElementChild;  // first child element
child.lastElementChild;   // last child element

// Siblings
child.nextElementSibling;     // next sibling element
child.previousElementSibling; // previous sibling element

// Closest ancestor matching selector
child.closest(".container"); // walks up DOM to find matching ancestor

Data Attributes

Custom data stored in HTML:

hljs javascript
// HTML: <div data-user-id="42" data-role="admin">

const el = document.querySelector("[data-user-id]");

// Access
el.dataset.userId; // "42" (camelCase access to data-user-id)
el.dataset.role;   // "admin"

// Set
el.dataset.status = "active"; // creates data-status attribute

// Read all
for (const [key, value] of Object.entries(el.dataset)) {
  console.log(key, value);
}
โ–ถTry it yourself

Key Takeaways

  • querySelector/querySelectorAll are the go-to selectors (CSS syntax)
  • Use textContent for user data (safe); innerHTML only for trusted HTML
  • classList methods (.add(), .remove(), .toggle()) are the clean way to manage classes
  • createDocumentFragment batches DOM insertions for better performance
  • el.dataset accesses data-* attributes as camelCase properties
  • Traverse the DOM with parentElement, children, nextElementSibling

Ready to test your knowledge?

Take a quiz on what you just learned.

Take the Quiz โ†’