VS Vikesh Singh

Courses JavaScript Lesson 7

JAVASCRIPT · LESSON 7 OF 18

The DOM: Selecting and Changing Page Elements

· 4 min read

Everything so far has lived inside the console. Now we connect JavaScript to the actual page — the DOM, short for Document Object Model. T

Everything so far has lived inside the console. Now we connect JavaScript to the actual page — the DOM, short for Document Object Model. The DOM is the browser's live, in-memory representation of your HTML, structured as a tree of objects. When JavaScript changes the DOM, the browser redraws the page immediately — that's the whole mechanism behind every interactive website you've ever used.

Selecting Elements With QuerySelector

The first skill is selecting elements. The modern, go-to method is querySelector, which uses the same syntax as CSS selectors.

<div id="greeting">Hello</div>
<p class="note">A note</p>
const greeting = document.querySelector("#greeting");
const note = document.querySelector(".note");
const allNotes = document.querySelectorAll(".note");
console.log(greeting.textContent);
console.log(allNotes.length);

querySelector returns the first matching element, or null if nothing matches — that null is important, because calling a method on null throws an error, which is one of the most common runtime errors beginners hit ("Cannot read properties of null"). Always double-check your selector matches something before relying on the result, especially while your script may be running before the element exists (see lesson 1's note on script placement and defer).

querySelectorAll returns every matching element, but as a NodeList, not a true array — close enough for basic looping, but if you want to use array methods like map or filter on it, convert it first with Array.from(allNotes).

Changing Content And Attributes

Once you have an element, you can read or change its content and attributes.

const title = document.querySelector("#greeting");
title.textContent = "Welcome, Vikesh Singh";
title.style.color = "blue";
title.classList.add("highlight");
title.setAttribute("data-user", "iron-man");

textContent sets the plain text inside an element — safe and simple. There's also innerHTML, which lets you insert actual HTML markup, but it comes with a real risk: if you ever insert innerHTML built from user-provided text, you open the door to injecting malicious scripts into your own page (a vulnerability called XSS). The practical rule: use textContent for plain text, and only use innerHTML with content you trust completely, such as a fixed template string you wrote yourself.

classList.add/remove/toggle is the standard way to change styling by adding or removing CSS classes, rather than fiddling with inline styles directly — it keeps your styling rules in CSS where they belong, and your JavaScript just flips switches.

const box = document.querySelector("#box");
box.classList.toggle("active");

toggle() adds the class if it's missing and removes it if it's present — perfect for things like a menu that opens and closes.

Creating And Appending Elements

Creating new elements from scratch is another core skill, especially once you start building lists dynamically from data (exactly like the posts array from the last lesson).

const list = document.querySelector("#post-list");

const posts = ["JavaScript Basics", "Advanced CSS"];

posts.forEach(title => {
  const item = document.createElement("li");
  item.textContent = title;
  list.appendChild(item);
});

createElement builds a new element in memory — it doesn't appear on the page yet. appendChild actually attaches it into the DOM tree, inside the chosen parent, which is the step that makes it visible. Forgetting appendChild (or its sibling, append) is a very common reason "my element isn't showing up even though I created it."

A quick but important performance tip: if you're adding many items in a loop, appending one-by-one like above causes the browser to potentially re-layout the page on each append for very large lists. For small lists like most real pages, this is completely fine and not worth worrying about — but know that for genuinely large lists, techniques exist (like building a DocumentFragment first) to batch the work. You don't need that yet; just know the concept exists for later.

Older Selection Methods

Besides querySelector, you'll also encounter getElementById and getElementsByClassName in older code and tutorials. They still work, but querySelector and querySelectorAll are generally preferred today because they accept any valid CSS selector, including combinations like "ul li.active" or "#form input[type=email]", rather than being limited to one specific kind of lookup. There's a small performance difference in theory, but for any normal-sized page it's not something worth worrying about — favor whichever is clearer to read, and in modern code that's almost always querySelector.

A final practical habit: when a DOM change doesn't seem to be taking effect, open the Elements panel in your browser's developer tools and watch it live while your script runs, rather than only trusting console.log. Seeing the actual markup change (or fail to change) in real time is often faster than reasoning about it purely from code, and it will directly confirm whether your selector matched the element you intended in the first place.

Put this into practice: in a blank HTML page, add an empty <ul id="list"></ul>, then write a script that creates three <li> elements with different text and appends them into that list. Then try changing one of their classes with classList.add and confirm the DOM updated instantly without a page reload — that instant update is the entire point of this lesson.