What Is the DOM in JavaScript?

Every time JavaScript changes what’s on a page — updating text, adding an element, reacting to a click — it’s working through the DOM. This guide covers what the DOM actually is and the core methods for selecting and modifying it.

If you’ve worked through our guides on connecting JavaScript to HTML and arrays, you’ve likely already used the DOM without necessarily naming it directly. This guide makes it explicit.

What the DOM Actually Is

According to MDN’s introduction to DOM scripting, the Document Object Model is a tree structure representation created by the browser, enabling the HTML structure to be accessed and manipulated by programming languages — the browser itself uses it to apply styling as it renders a page, and developers can manipulate it with JavaScript after the page has loaded.

In simpler terms: when your browser loads an HTML page, it builds an internal, JavaScript-accessible tree representing every element — this tree is the DOM, and it’s what JavaScript actually interacts with, not the raw HTML text itself.

Selecting Elements

Before you can change anything, you need to select the element you want to work with. The most common modern method is querySelector(), which accepts a CSS-style selector:

const heading = document.querySelector("h1");
const firstButton = document.querySelector(".btn");
const specificItem = document.querySelector("#item-3");

To select multiple matching elements at once, use querySelectorAll(), which returns a list you can loop through.

Changing Content

const heading = document.querySelector("h1");
heading.textContent = "New heading text";

textContent changes the plain text inside an element. For content that includes HTML tags, innerHTML does the equivalent job — but it’s worth using carefully, since inserting unchecked user-provided content with innerHTML can introduce security vulnerabilities.

Changing Styles

const box = document.querySelector(".box");
box.style.backgroundColor = "yellow";
box.style.fontSize = "20px";

CSS properties with hyphens (like background-color) become camelCase in JavaScript (backgroundColor) — a small but consistent naming convention worth remembering.

Creating and Adding New Elements

const newItem = document.createElement("li");
newItem.textContent = "New list item";
document.querySelector("ul").appendChild(newItem);

This creates a brand-new element entirely in memory, sets its content, then attaches it to an existing element already in the page — the standard three-step pattern for adding something new dynamically.

Removing Elements

const item = document.querySelector(".old-item");
item.remove();

Reacting to Events

The DOM is also how JavaScript listens for user interaction:

const button = document.querySelector("button");
button.addEventListener("click", function() {
  console.log("Button was clicked!");
});

According to freeCodeCamp’s DOM manipulation handbook, when an event occurs, it propagates — traveling either from the element where it happened outward to the page’s outermost elements, or vice versa — which becomes relevant once you’re handling clicks on nested or dynamically created elements.

Traversing the DOM: Moving Between Related Elements

Once you’ve selected one element, you often need to reach a related one — its parent, its children, or its siblings — without writing a whole new selector. According to freeCodeCamp’s beginner’s guide to DOM manipulation, the DOM tree starts with the document object, with the html element as its child, and body and head as siblings beneath that — the same nested, parent-child structure your HTML markup already describes.

const item = document.querySelector(".list-item");
console.log(item.parentElement);   // the containing element
console.log(item.children);        // any nested child elements
console.log(item.nextElementSibling); // the next element at the same level

These traversal properties are genuinely useful once you’re working with dynamically generated content, where you don’t always have a unique selector for exactly the element you need — instead, you select something you can easily target, then navigate from there.

Working With Classes

Rather than setting individual style properties one at a time, it’s often cleaner to toggle a CSS class and let your stylesheet define what that class actually looks like:

const box = document.querySelector(".box");
box.classList.add("highlighted");
box.classList.remove("highlighted");
box.classList.toggle("highlighted");

classList.toggle() is especially handy for things like show/hide behavior or active-state buttons — it adds the class if it’s missing and removes it if it’s already there, in a single line, without needing an if/else check yourself.

A Practical Example: A Simple Counter

Here’s a small, complete example tying several DOM concepts together:

let count = 0;
const display = document.querySelector("#count");
const button = document.querySelector("#increment");

button.addEventListener("click", function() {
  count++;
  display.textContent = count;
});

This selects two elements, listens for a click, updates a variable, and reflects that change back into the page — the exact pattern behind a huge share of everyday interactive JavaScript, from like buttons to shopping cart counters.

Common Questions

Is the DOM the same as the HTML source code? No — the DOM is the browser’s live, in-memory representation, which can differ from the original HTML once JavaScript has made changes. Viewing “page source” shows the original HTML; DevTools’ Elements panel shows the current DOM.

Why use querySelector instead of older methods like getElementById? querySelector accepts any valid CSS selector, making it more flexible and consistent with the same syntax you already know from CSS — older methods still work but are more limited in what they can target, and it’s simpler to only need to remember one selection syntax.

Does manipulating the DOM change the original HTML file? No — DOM changes only affect what’s currently loaded in the browser’s memory for that session. Refreshing the page reloads the original HTML file fresh, discarding any JavaScript-driven changes that were made before the reload.

Handling Multiple Elements at Once

querySelectorAll() returns a NodeList — similar to an array — containing every element matching the selector. Looping through it lets you apply the same change to multiple elements at once:

const items = document.querySelectorAll(".list-item");
items.forEach(item => {
  item.style.color = "blue";
});

This pattern shows up constantly once you’re working with lists, grids, or any repeated structure — selecting every matching element once, then looping to apply a change to each one individually, rather than manually selecting and updating them one at a time.

Quick-Reference Guide

  • DOM — the browser’s live tree representation of a page.
  • querySelector() / querySelectorAll() — select one or multiple elements using CSS selectors.
  • textContent / innerHTML — change an element’s content.
  • style.property — change CSS directly via JavaScript.
  • createElement() + appendChild() — add new elements dynamically.
  • addEventListener() — react to clicks and other user interactions.

Conclusion

The DOM is the bridge between static HTML and the interactive behavior covered throughout our JavaScript guides — every dynamic change to a page routes through selecting, then modifying, DOM elements. Getting comfortable with querySelector, content changes, and event listeners covers the overwhelming majority of everyday DOM work.

In the next guide in this series, we’ll cover common JavaScript mistakes beginners make, closing out the fundamentals covered throughout this series.

Explore More JavaScript Basics Guides →

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top