JAVASCRIPT / LESSON 09

Find and change page elements with the DOM

Select existing elements and create new content safely.

Content updated

By the end, you can…

  • The DOM is the browser's object representation of the page. Select an element before changing it.
  • Predict the example's result, change one part, and verify the behavior in your own script.
Before you begin

One idea at a time

The browser parses HTML into a tree of nodes called the Document Object Model, or DOM. A node is one part of that tree, such as an element or a piece of text. JavaScript can read and change that tree through document. The HTML file is your starting source; changing the DOM updates the current page in memory, not the saved file on disk. Reloading starts again from the file.

A selector finds an existing element. document.querySelector accepts a CSS selector and returns the first match, or null when nothing matches. Match the spelling and capitalization of the HTML id. Use an external deferred script so the elements exist before your code runs. Finding an element does not automatically change it.

What to remember first

Remember first

The DOM is the browser's object representation of the page. Select an element before changing it.

Read the code before trying it

document.querySelector("#heading")Find the first match
# introduces an id selector, while the HTML id value itself has no #.
document.getElementById("heading")Find by id directly
Pass the id without #. querySelectorAll instead returns a collection of matching nodes.
element.textContentRead or replace text
User text stays text, even when it contains angle brackets. innerHTML parses markup, so do not use it for untrusted input.
document.createElement("li")Create a new element
The element starts detached. Set its text, then append it to a parent to show it.
parent.append(child)Insert a node
This adds the child at the end. remove() detaches an existing element.
element.style.colorSet an inline style
For larger visual changes, prefer a stylesheet and classList.add or classList.remove rather than many inline assignments.

Walk through an example

html
<h2 id="heading">My notebook</h2>
<ul id="topics"></ul>
javascript
const heading = document.querySelector("#heading");
heading.textContent = "Topics to explore";
const list = document.querySelector("#topics");
const item = document.createElement("li");
item.textContent = "JavaScript";
list.append(item);

The h2 and ul already exist. The first two statements change the h2 text. createElement makes a new li, textContent gives it a label, and append places it inside the list. Without append, the item exists only as a detached object and is not visible in the document.

See it happen: try a small change

Find and change page elements with the DOM: try it

Predict the result, choose a version, then compare the code and output. Try the controls when the example has them. Each version starts fresh.

Code to notice

document.querySelector("#heading").textContent = "Topics to explore";
const item = document.createElement("li");
item.textContent = "JavaScript";
document.querySelector("#topics").append(item);

Live result

Lesson example
index.htmlPreview

What changed: The existing heading changes; a new li is appended inside the existing ul.

Look a little closer

A selection can fail without throwing: querySelector returns null. Trying to set textContent on that null value fails afterward. Check the selector, the HTML, and script timing. In code where an element is optional, test whether it exists before using it; do not silently hide a missing required element while debugging.

querySelectorAll returns a NodeList, a collection of nodes. Static means its membership is a snapshot taken when the selection runs, rather than a live list. You can visit its elements with for...of, just as you visited array values. The collection will not automatically gain nodes you create later. textContent includes text without checking layout, whereas innerText considers rendered text. For these straightforward updates, textContent keeps the behavior predictable.

Try it in your own project

Put the supplied h2 and empty ul in body and keep the deferred script link in head. Use two distinct li objects for two books; appending the same node again moves it rather than making a copy. Reload to verify the script rebuilds exactly two items.

The interactive preview runs in its own isolated document. Its Output panel mirrors console.log messages; it is not a full DevTools console. Choosing another version or resetting starts a fresh example and does not edit your local files. Read any simulation label: storage and request demonstrations explain their offline substitutes, while the written local examples use the real browser APIs.

A common wrong turn

Using a class selector with #, omitting # for an id in querySelector, or running before the markup exists can all produce no match. Changing a value in your script also does not refresh the DOM by itself; explicitly assign the new text when you want it displayed.

Your turn: find and change page elements with the DOM

Build a reading list using existing HTML and one new list item created by JavaScript.

Try this in your own HTML and JavaScript files, then open the page in a browser. There is no separate checked practice for this task yet.

  1. Put the h2 and ul above in your HTML body, with your deferred script linked.
  2. Change the heading text and append two li elements with different titles.
  3. Reload and check that both items return exactly once. Try a missing selector in the Console and explain why its result is null.

Go to the source

Examples are authored for Tuklas and checked with code and reference documentation. This is not a claim of independent human review. Suggest a correction.