The DOM

Course 1 · Ch 8
The DOM: Selecting and Manipulating HTML Elements
Where JavaScript stops being abstract — reaching into a real page and changing what's actually on screen

Every chapter so far has run entirely in the console. The DOM (Document Object Model) is the browser's live, in-memory representation of the HTML page — and JavaScript can read and change it directly, which is how a page updates without a reload. This chapter is the bridge between "writing JavaScript" and "JavaScript that actually does something visible."

Selecting a Single Element

const heading = document.querySelector("h1"); const box = document.querySelector("#intro"); const firstItem = document.querySelector(".list-item"); console.log(heading);

document.querySelector() takes a CSS selector — the same syntax used in a stylesheet — and returns the first matching element on the page, or null if nothing matches. #intro selects by ID, .list-item by class, exactly as in CSS.

Selecting Multiple Elements

const items = document.querySelectorAll(".list-item"); console.log(items.length); // however many .list-item elements exist items.forEach(item => { console.log(item.textContent); });

querySelectorAll() returns every matching element as a NodeList — array-like enough that forEach from Chapter 6 works directly on it, even though it's technically not a true array.

querySelector vs querySelectorAll
Use querySelector when exactly one element is expected (often by ID). Use querySelectorAll whenever there could be several matches (a class shared by many elements) and all of them need handling.

Reading and Changing Text Content

const heading = document.querySelector("h1"); console.log(heading.textContent); // reads the current text heading.textContent = "Updated by JavaScript"; // changes it on the page, instantly

textContent is a property on the element, just like the object properties from Chapter 7 — reading it returns the current text, and assigning to it updates the page immediately, with no reload required.

Changing Styles and Classes

box.style.color = "red"; // inline style, one property at a time box.style.backgroundColor = "#222"; box.classList.add("highlighted"); // adds a CSS class box.classList.remove("highlighted"); // removes it box.classList.toggle("highlighted"); // adds if missing, removes if present

element.style sets individual CSS properties directly (camelCase instead of CSS's hyphenated names — backgroundColor, not background-color). classList is almost always the better choice for anything beyond a one-off tweak, since it keeps styling rules in CSS where they belong and JavaScript just toggles which rules apply.

Responding to Events

const button = document.querySelector("#myButton"); button.addEventListener("click", () => { console.log("Button was clicked!"); button.textContent = "Clicked!"; });

addEventListener takes an event name ("click", "input", "submit", and many others) and a function to run when that event happens. This is the first genuinely common, practical use for the function-as-a-value behaviour from Chapter 5 — the function itself is handed over and the browser calls it later, whenever the click actually occurs.

Run your script after the page has loaded
If a <script> runs before the HTML below it exists yet, querySelector returns null and calling a method on it throws an error. Either place scripts at the end of <body>, or wrap the code in document.addEventListener("DOMContentLoaded", () => { ... }).

Creating New Elements

const list = document.querySelector("#myList"); const newItem = document.createElement("li"); newItem.textContent = "A brand new item"; list.appendChild(newItem); // inserts it at the end of the list

createElement builds a new element entirely in memory — it doesn't appear on the page until it's attached somewhere with appendChild (or a similar method). This pattern — combined with an array of data and a loop — is how real pages render dynamic lists.

TaskMethod/Property
Select one elementdocument.querySelector(selector)
Select all matching elementsdocument.querySelectorAll(selector)
Read/change textelement.textContent
Read/change one CSS propertyelement.style.property
Add/remove/toggle a CSS classelement.classList.add/remove/toggle()
Run code on an eventelement.addEventListener(event, fn)
Build a new elementdocument.createElement(tag)

Coding Challenges

Challenge 1

Assume the page has a

Hello

. Select it with querySelector, log its current textContent, then change its text to "Updated!" and change its color to blue using element.style.

📄 View solution
Challenge 2

Assume the page has a button with id toggleBtn and a div with id panel. Add a click event listener to the button that toggles a class called "open" on panel each time it's clicked, using classList.toggle.

📄 View solution
Challenge 3

Given const fruits = ["Apple", "Banana", "Cherry"] and an empty

    on the page, write code that creates a new li element for each fruit (using createElement and textContent) and appends each one to fruitList.

    📄 View solution

    Chapter 8 Quick Reference

    • querySelector(selector) — first matching element, or null
    • querySelectorAll(selector) — all matching elements, as a NodeList (forEach works on it)
    • element.textContent — read or change an element's text
    • element.style.property — set one CSS property directly (camelCase)
    • element.classList.add/remove/toggle() — preferred way to change appearance via CSS classes
    • element.addEventListener(event, fn) — run a function when something happens (click, input, etc.)
    • document.createElement(tag) + appendChild() — build and insert new elements dynamically
    • Run scripts after the HTML exists — end of body, or inside a DOMContentLoaded listener
    • Next chapter: forms and user input — reading values, validating, and responding to submission