← Back to JavaScript series
🎯
DOM
Intermediate Β· Prerequisite: 16_async_await

17. DOM Selection and Inspection

The browser parses HTML into a DOM (Document Object Model) tree. JavaScript reads and updates this tree to change what the user sees.

DOMquerySelectorgetElementByIdinspection
Duration
⏱ ~1 hour
Level
πŸ“Š Intermediate
Prerequisite
🎯 Lecture 16
OUTCOME
The browser parses HTML into a DOM (Document Object Model) tree. JavaScript reads and updates this tree to change what the user sees.

What you'll learn

  • 1Understand the DOM tree.
  • 2Select elements with `querySelector`, `querySelectorAll`, `getElementById`.
  • 3Read attributes with `getAttribute` and `dataset`.
  • 4Know the difference between `textContent` and `innerHTML` (especially XSS).
  • 5Navigate parent/child/sibling nodes.

Overview

The browser parses HTML into a DOM (Document Object Model) tree. JavaScript reads and updates this tree to change what the user sees.

Core Concepts

1. What is the DOM?

The browser parses HTML into a DOM (Document Object Model) tree. JavaScript reads and updates this tree to change what the user sees.

2. Selecting elements

javascript
const title = document.querySelector("#title");           // first match
const items = document.querySelectorAll(".item");         // NodeList
const byId = document.getElementById("title");

`querySelector` accepts a regular CSS selector. `querySelectorAll` returns a static NodeList that supports forEach.

3. Reading attributes

javascript
const link = document.querySelector("a");
link.getAttribute("href");
link.href;                  // DOM property
link.dataset.userId;        // the data-user-id attribute

4. textContent vs innerHTML

`textContent` reads/writes plain text, so it's safe. `innerHTML` parses an HTML string, so dropping user input into it exposes you to XSS. Always use `textContent` for external input, or sanitize first.

5. Tree navigation

javascript
el.parentElement;
el.children;
el.firstElementChild;
el.nextElementSibling;

Examples

FileWhat it covers
index.htmlHTML page used by the examples
01_query_selector.jsquerySelector/All in use
02_attributes.jsgetAttribute / dataset
03_text_html.jstextContent vs innerHTML
04_nested.jsParent/child/sibling traversal

src/01_query_selector.js

javascript
/**
 * Compare querySelector / querySelectorAll / getElementById.
 */
const title = document.querySelector("#title");
console.log("title:", title.textContent);

const items = document.querySelectorAll(".item");
console.log("item count:", items.length);
items.forEach((el) => console.log("-", el.textContent));

const byId = document.getElementById("msg");
console.log("msg:", byId.textContent);

src/02_attributes.js

javascript
/**
 * Read attributes and dataset.
 */
const link = document.querySelector("#link");
console.log("href(attr):", link.getAttribute("href"));
console.log("href(prop):", link.href);

document.querySelectorAll(".item").forEach((el) => {
  console.log("id =", el.dataset.id, ", text =", el.textContent);
});

src/03_text_html.js

javascript
/**
 * Differences between textContent and innerHTML.
 * Putting user input directly into innerHTML is an XSS risk.
 */
const msg = document.querySelector("#msg");
console.log("textContent:", msg.textContent);
console.log("innerHTML:", msg.innerHTML);

msg.textContent = "<b>safe</b>";
console.log("after textContent:", msg.textContent);

src/04_nested.js

javascript
/**
 * Parent / child / sibling traversal.
 */
const list = document.querySelector("#list");
console.log("children:", list.children.length);
console.log("first child:", list.firstElementChild.textContent);
console.log("second child:", list.firstElementChild.nextElementSibling.textContent);
console.log("parent tag:", list.parentElement.tagName);

src/index.html

html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>DOM selection and inspection</title>
  </head>
  <body>
    <h1 id="title">DOM example</h1>
    <ul id="list">
      <li class="item" data-id="1">apple</li>
      <li class="item" data-id="2">banana</li>
      <li class="item" data-id="3">cherry</li>
    </ul>
    <a href="https://example.com" id="link">example link</a>
    <p id="msg">Hello</p>

    <script src="01_query_selector.js"></script>
    <script src="02_attributes.js"></script>
    <script src="03_text_html.js"></script>
    <script src="04_nested.js"></script>
  </body>
</html>

Common Mistakes

  1. Loading a script in `<head>` and trying to touch the DOM before it exists.
  2. Treating `querySelectorAll` results as arrays β€” they're NodeLists, you may need `Array.from`.
  3. Putting user input directly into `innerHTML`.
  4. Ignoring the subtle difference between `getAttribute("class")` and `el.className`.
  5. Relying on a behavior when multiple elements share the same id.

FAQ

Q1. getElementById or querySelector("#id")?

The performance difference is negligible. Use querySelector consistently if you prefer.

Q2. NodeList vs HTMLCollection?

NodeList is static (or live); HTMLCollection is always live and has no forEach.

Q3. dataset naming rules?

data-user-id maps to dataset.userId (kebab-case β†’ camelCase).

Practice

Select every element with a given class in your page and print the list to the console.

homework/README.md

Select every `.fruit` item in the HTML and print:

  1. The text of each item
  2. The value of its data-color attribute

See `answer/homework_01.html` and `answer/homework_01.js` for the solution.

homework/answer/homework_01.html

html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Homework 17-1</title>
  </head>
  <body>
    <ul id="fruits">
      <li class="fruit" data-color="red">apple</li>
      <li class="fruit" data-color="yellow">banana</li>
      <li class="fruit" data-color="purple">grape</li>
    </ul>
    <script src="homework_01.js"></script>
  </body>
</html>

homework/answer/homework_01.js

javascript
/**
 * Print the text and color of every .fruit element.
 */
const fruits = document.querySelectorAll(".fruit");
fruits.forEach((el) => {
  console.log(`${el.textContent} -> ${el.dataset.color}`);
});

Next Lecture

[18_DOM_Manipulation](../18_DOM_μ‘°μž‘/) β€” Creating, inserting, and removing elements.

Example code / lecture materials

All lecture materials and example code are openly available on GitHub.

View on GitHub β†—