Skip to content
WANCODE
BM

Understanding the DOM: JavaScript Meets the Page

18 minBeginnerHTML · CSS · JS

In this lesson

  • Explain how the browser turns HTML into a tree of objects (the DOM)
  • Select elements with querySelector / querySelectorAll and change them with textContent and classList
  • Create elements with createElement and append, and know why innerHTML with user input is risky

The big idea

When the browser reads your HTML, it builds a tree of JavaScript objects called the DOM. Change those objects and the page on screen changes with them.

So far your code has only talked to the Console. Now it gets to touch the actual page. The bridge is the DOM (Document Object Model): every tag in your HTML becomes an object your script can find, read and change.

Nested tags become a tree: each element is a node with a parent and children.

Finding elements

JavaScript
// One element: the FIRST match for a CSS selector (or null)
const title = document.querySelector("#title");
const firstItem = document.querySelector(".item");

// Every match, as a list you can loop over
const items = document.querySelectorAll(".item");
console.log(items.length); // 3

for (const item of items) {
  console.log(item.textContent);
}

The "Cannot read properties of null" error

This famous error means querySelector found nothing, so you're using null as if it were an element. Check the selector's spelling (# for id, . for class), and make sure the <script> tag comes after the HTML it uses — that's why it sits at the end of <body>.

Changing text and classes

JavaScript
const statusText = document.querySelector("#status");
statusText.textContent = "Open today!";   // replace the text

statusText.classList.add("highlight");    // add a class
statusText.classList.remove("highlight"); // remove it
statusText.classList.toggle("highlight"); // add if missing, remove if present
statusText.classList.contains("highlight"); // true / false

Prefer toggling classes over setting styles one by one: the look stays in CSS, the logic stays in JavaScript.

textContent vs innerHTML

innerHTML — parses the string as HTML

JavaScript
note.innerHTML = "<b>Hi</b>";
// shows: Hi (in bold — a real <b> element)

note.innerHTML = userInput; // ⚠ dangerous

textContent — always plain text

JavaScript
note.textContent = "<b>Hi</b>";
// shows: <b>Hi</b> (exactly those characters)

note.textContent = userInput; // ✓ safe

If you put text a user typed into innerHTML, they can type HTML — including tags that run JavaScript. This attack is called cross-site scripting (XSS), and it's one of the most common security bugs on the web. Rule of thumb: user text goes in textContent. Only use innerHTML for HTML you wrote yourself.

Creating new elements

JavaScript
const li = document.createElement("li"); // 1. create (not on the page yet)
li.textContent = "Kuih lapis";            // 2. fill it
li.classList.add("item");                 // 3. style it

document.querySelector("#menu").append(li); // 4. attach it → now it's visible

Under Step 1 in script.js:

1. Select all .item elements and add the class highlight to each one (the CSS for it is ready).

2. Replace the Loading menu… text in #status with a message that includes how many items there are, e.g. 3 items on the menu. Count them with JavaScript — don't type the number by hand.

Checks

  • #status shows the number of items
  • Every .item has the highlight class

Check understanding

Q1

document.querySelector("#menu") returns null. What's the most likely cause?

Q2

A user types <img src=x onerror="…"> into a comment box. Which line displays it safely?

Q3

You ran const li = document.createElement("li"); li.textContent = "Hi"; but nothing appears. Why?

What you learned

  • The DOM is the browser's tree of objects built from your HTML — change it and the page changes.
  • querySelector gets the first match (or null); querySelectorAll gets all matches to loop over.
  • classList switches looks on and off; createElement + append adds new things.
  • User text goes in textContent, never innerHTML.
Preview

Console output from your code appears here.

Step 1 of 3