
Quick answer: The JavaScript DOM is the browser’s object model of your page. Select elements with querySelector and querySelectorAll, change them with properties like textContent, classList and setAttribute, create nodes with document.createElement, and insert them with append. Prefer changing classes rather than inline styles so CSS keeps control of appearance.The sections below follow the JavaScript DOM in the order you use it: selecting elements, changing content, creating nodes, attributes and properties, then the ordering mistake behind most JavaScript DOM bugs.
Table of Contents
Selecting elements in the JavaScript DOM
const title = document.querySelector("h1"); // first match
const items = document.querySelectorAll(".card"); // all matches (a NodeList)
const byId = document.getElementById("hero"); // fastest for an id
items.forEach(el => el.classList.add("visible")); // NodeList is iterablequerySelector takes any CSS selector, so everything from the previous CSS articles applies here. Both queries return null or an empty list when nothing matches, so check before you use the result.
Reading and changing content
title.textContent = "Welcome, Ada"; // text only — safe
title.innerHTML = "<em>Hi</em>"; // parses HTML — risky with user input
const button = document.querySelector("button");
button.classList.add("is-active");
button.classList.toggle("is-open");
button.classList.remove("is-active");
button.dataset.role = "submit"; // sets data-role attributeUse textContent for anything that might contain user data. innerHTML parses a string as HTML, which opens the door to cross-site scripting if the string came from a form or an API. When you need to change appearance, change a class — the styling stays in CSS where you can reason about it.
Creating and inserting nodes
const list = document.querySelector("#todos");
const li = document.createElement("li");
li.textContent = "Buy milk";
li.classList.add("item");
list.append(li); // add at the end
list.prepend(li); // add at the start
li.before(otherLi); // insert before a sibling
li.remove(); // take it out of the DOMFor a long list, build the markup off to the side and insert once. Touching the DOM repeatedly forces repeated reflow, so batching thousands of inserts into a single append or a DocumentFragment is markedly faster.
const frag = document.createDocumentFragment();
items.forEach(item => {
const li = document.createElement("li");
li.textContent = item.name;
frag.append(li);
});
list.append(frag); // one DOM operation for the whole batchAttributes and properties
Most HTML attributes have a matching DOM property, and the property is usually what you want because it reflects the current state.
const input = document.querySelector("input");
input.value = "hello"; // current value, not the attribute
input.disabled = true; // boolean property
input.setAttribute("aria-label", "Search"); // attribute, for ARIA
input.getAttribute("type"); // "text"Use properties for state the user controls — value, checked, disabled — and setAttribute for attributes that only exist in markup, such as aria-* and data-*.
Avoiding the black screen of nothing in the JavaScript DOM
The most common beginner error is running script before the DOM exists. Put your <script> at the end of the body, or use defer on a script in the head, so the elements you query are already parsed.
<script src="app.js" defer></script>Next: events, which make the page react to the user. To learn the DOM with a mentor on real pages, Ampersand Academy teaches web development one-to-one.
Frequently asked questions
What is the difference between textContent and innerHTML?
textContent sets plain text and is safe with any input. innerHTML parses its string as HTML, which allows cross-site scripting if the string includes user data.
Why is querySelector returning null?
Usually the script runs before the element exists in the DOM. Put the script at the end of the body or add the defer attribute so elements are parsed first.
How do I add a CSS class with JavaScript?
Use element.classList.add, remove or toggle. Changing classes keeps styling in CSS and is clearer than setting inline styles from script.
What is a DocumentFragment used for?
It is an offscreen container for building several nodes at once, so you can insert them into the page in a single DOM operation instead of many.
Should I use getElementById or querySelector?
getElementById is faster for a single id, while querySelector accepts any CSS selector and is more flexible. Both return null when nothing matches, so check the result.
Last updated on · Written by Dinesh Kumar R

