LearnContact
Lesson 2165 min read

JavaScript DOM

Learn how JavaScript interacts with HTML using the Document Object Model. Master element selection, content manipulation, attributes, styles, classes, element creation, traversal, forms, collections, and dynamic web page updates.

Introduction

HTML creates the structure of a web page, CSS controls its appearance, and JavaScript adds behavior. However, JavaScript needs a way to find, read, change, create, and remove HTML elements. The Document Object Model, commonly called the DOM, provides this connection.

The DOM represents an HTML document as a tree of JavaScript objects. Every heading, paragraph, button, image, form, attribute, and text value becomes part of this object structure.

Using the DOM, JavaScript can change text, update images, modify styles, add or remove CSS classes, create new elements, delete existing elements, read form values, build dynamic interfaces, and much more.

What You Will Learn
  • What the Document Object Model is.
  • Why JavaScript needs the DOM.
  • How browsers convert HTML into a DOM tree.
  • What DOM nodes are.
  • The different types of DOM nodes.
  • What the document object represents.
  • How to select HTML elements.
  • How getElementById() works.
  • How getElementsByClassName() works.
  • How getElementsByTagName() works.
  • How querySelector() works.
  • How querySelectorAll() works.
  • How to use CSS selectors in JavaScript.
  • How to read and change text content.
  • The difference between textContent, innerText, and innerHTML.
  • How to read and modify attributes.
  • How to work with custom data attributes.
  • How to change inline styles.
  • How to read computed styles.
  • How to add, remove, toggle, check, and replace CSS classes.
  • How to create new HTML elements.
  • How to insert elements into the document.
  • How to remove elements.
  • How to replace elements.
  • How to clone elements.
  • How to navigate between parent, child, and sibling elements.
  • How closest() and matches() work.
  • The difference between HTMLCollection and NodeList.
  • How to loop through selected elements.
  • How to work with forms and input elements.
  • How to read element dimensions.
  • How to find an element position.
  • How to scroll elements into view.
  • How script placement affects DOM access.
  • How to build a complete dynamic DOM application.

What is the DOM?

DOM stands for Document Object Model. It is a programming interface created by the browser that represents an HTML document as a structured tree of objects.

The word Document refers to the loaded web page. Object means that parts of the document are represented as programmable objects. Model means that these objects are organized into a structured representation.

DOM Meaning
D O M

D → Document

    The HTML web page


O → Object

    HTML elements become objects


M → Model

    Objects are organized
    in a tree structure
HTML Document
<h1 id="title">
    Welcome
</h1>

<p>
    Learn JavaScript DOM.
</p>
JavaScript Access
const title =
    document.getElementById(
        'title'
    );

console.log(title);
Console Output

Why Do We Need the DOM?

Without the DOM, JavaScript would not have a standard way to interact with the visible HTML document. The DOM gives JavaScript access to page structure and content.

Find Elements

Select headings, buttons, forms, images, cards, and other elements.

Change Content

Update text, HTML content, labels, messages, and displayed values.

Change Appearance

Modify styles and CSS classes dynamically.

Create Elements

Generate cards, list items, notifications, tables, and other content.

Remove Elements

Delete elements that are no longer needed.

Work with Forms

Read and update input, checkbox, radio, and select values.

Build Interfaces

Create menus, tabs, modals, accordions, and dashboards.

Update Pages

Change the page without reloading the entire document.

Display Data

Convert JavaScript data into visible HTML content.

Add Interactivity

Combine DOM manipulation with events to respond to users.

Real-World Analogy

Think of an HTML document as a house and the DOM as a detailed map of that house. JavaScript uses the map to locate and modify individual parts.

House Analogy
HTML WEB PAGE

        HOUSE
          │
          ▼

┌──────────────────────────────┐
│            ROOM              │
│                              │
│   ┌────────┐  ┌──────────┐   │
│   │ TABLE  │  │  CHAIR   │   │
│   └────────┘  └──────────┘   │
│                              │
│   ┌──────────────────────┐   │
│   │        WINDOW        │   │
│   └──────────────────────┘   │
└──────────────────────────────┘


DOM MAP

document
   │
   └── room
        │
        ├── table
        │
        ├── chair
        │
        └── window


JAVASCRIPT

Find the chair
      │
      ▼
Change its appearance
      │
      ▼
Move or remove it

How the DOM Works

When a browser loads an HTML file, it reads the HTML source code and converts it into a DOM tree. JavaScript then interacts with this tree rather than directly editing the original HTML file.

DOM Creation Process
HTML FILE

index.html

    │
    ▼

BROWSER READS HTML

    │
    ▼

HTML IS PARSED

    │
    ▼

DOM TREE IS CREATED

    │
    ▼

JAVASCRIPT ACCESSES DOM

    │
    ├── Find Elements
    │
    ├── Read Content
    │
    ├── Change Content
    │
    ├── Change Styles
    │
    ├── Create Elements
    │
    └── Remove Elements
    │
    ▼

VISIBLE PAGE UPDATES
Important Concept
  • The HTML file contains source code.
  • The browser parses the HTML.
  • The browser creates the DOM.
  • JavaScript works with the DOM representation.
  • DOM changes update the currently displayed page.
  • Changing the DOM does not automatically rewrite the original HTML file.

HTML to DOM Tree

index.html
<!DOCTYPE html>
<html>
<head>
    <title>My Page</title>
</head>
<body>
    <h1>Welcome</h1>

    <p>
        Learn JavaScript.
    </p>
</body>
</html>
DOM Tree
document
   │
   └── html
        │
        ├── head
        │    │
        │    └── title
        │         │
        │         └── "My Page"
        │
        └── body
             │
             ├── h1
             │    │
             │    └── "Welcome"
             │
             └── p
                  │
                  └── "Learn JavaScript."

The DOM has a hierarchical structure. Elements can contain other elements, and these relationships are described using terms such as parent, child, and sibling.

DOM Nodes

Everything in the DOM tree is represented as a node. Elements, text, comments, and the document itself are different types of nodes.

HTML Example
<p id="message">
    Hello World
</p>
Node Structure
ELEMENT NODE

<p id="message">
        │
        ▼
TEXT NODE

"Hello World"


The id attribute belongs
to the element.

Types of DOM Nodes

Document Node

Represents the entire HTML document.

Element Node

Represents HTML elements such as div, p, button, and input.

Text Node

Represents text inside an HTML element.

Comment Node

Represents an HTML comment.

Attribute Data

Represents information associated with element attributes.

Different Nodes
<!-- Comment Node -->

<section>
    <h2>
        DOM Nodes
    </h2>
</section>
Node Tree
DOCUMENT NODE
      │
      ├── COMMENT NODE
      │
      └── ELEMENT NODE
           │
           └── section
                │
                └── ELEMENT NODE
                     │
                     └── h2
                          │
                          └── TEXT NODE
                               │
                               └── "DOM Nodes"

The document Object

The document object represents the currently loaded HTML document. It is the main entry point for accessing and manipulating the DOM.

Document Object
console.log(document);

The document object provides properties and methods for finding elements, creating elements, reading document information, and modifying the page.

Document Properties
console.log(
    document.title
);

console.log(
    document.URL
);

console.log(
    document.body
);

console.log(
    document.head
);

Accessing the Document

index.html
<!DOCTYPE html>
<html>
<head>
    <title>DOM Course</title>
</head>
<body>
    <h1>JavaScript DOM</h1>
</body>
</html>
Access Document Information
console.log(
    document.title
);

console.log(
    document.documentElement
);

console.log(
    document.head
);

console.log(
    document.body
);
Example Console Output

Selecting Elements

Before JavaScript can modify an HTML element, it usually needs to select that element. The document object provides several methods for finding elements.

Element Selection Methods
document
   │
   ├── getElementById()
   │
   ├── getElementsByClassName()
   │
   ├── getElementsByTagName()
   │
   ├── querySelector()
   │
   └── querySelectorAll()

getElementById()

The getElementById() method selects an element using its id attribute. Since an id should be unique within a document, this method returns one element or null.

index.html
<h1 id="title">
    JavaScript DOM
</h1>
Select by ID
const title =
    document.getElementById(
        'title'
    );

console.log(title);
Console Output
Element Not Found
const element =
    document.getElementById(
        'unknown'
    );

console.log(element);
Output

getElementsByClassName()

The getElementsByClassName() method selects all elements containing a specified class and returns a live HTMLCollection.

index.html
<p class="message">First</p>
<p class="message">Second</p>
<p class="message">Third</p>
Select by Class
const messages =
    document.getElementsByClassName(
        'message'
    );

console.log(messages);

console.log(
    messages.length
);
Output
Access Individual Element
const messages =
    document.getElementsByClassName(
        'message'
    );

console.log(
    messages[0]
);

console.log(
    messages[1]
);

getElementsByTagName()

The getElementsByTagName() method selects elements by their HTML tag name and returns a live HTMLCollection.

index.html
<p>Paragraph One</p>
<p>Paragraph Two</p>
<p>Paragraph Three</p>
Select by Tag Name
const paragraphs =
    document.getElementsByTagName(
        'p'
    );

console.log(
    paragraphs.length
);
Output

querySelector()

The querySelector() method accepts a CSS selector and returns the first matching element. If no element matches, it returns null.

index.html
<h1 id="title">
    DOM Course
</h1>

<p class="message">
    First Message
</p>

<p class="message">
    Second Message
</p>
querySelector Examples
const title =
    document.querySelector(
        '#title'
    );

const message =
    document.querySelector(
        '.message'
    );

const paragraph =
    document.querySelector(
        'p'
    );

console.log(title);
console.log(message);
console.log(paragraph);
querySelector() Returns One Element
  • It accepts any valid CSS selector.
  • It returns only the first matching element.
  • It returns null when no match exists.
  • Use # for an ID selector.
  • Use . for a class selector.
  • Use the tag name for an element selector.

querySelectorAll()

The querySelectorAll() method accepts a CSS selector and returns a static NodeList containing all matching elements.

index.html
<p class="message">One</p>
<p class="message">Two</p>
<p class="message">Three</p>
Select All Matching Elements
const messages =
    document.querySelectorAll(
        '.message'
    );

console.log(messages);

console.log(
    messages.length
);
Output
Loop Through NodeList
const messages =
    document.querySelectorAll(
        '.message'
    );

messages.forEach(
    function (message) {
        console.log(
            message.textContent
        );
    }
);
Output

Selection Methods Comparison

DOM Selection Comparison
Method
────────────────────────────────────────────

getElementById()

Selector:
ID value without #

Returns:
Single Element or null


getElementsByClassName()

Selector:
Class name without .

Returns:
Live HTMLCollection


getElementsByTagName()

Selector:
Tag name

Returns:
Live HTMLCollection


querySelector()

Selector:
Any CSS selector

Returns:
First Element or null


querySelectorAll()

Selector:
Any CSS selector

Returns:
Static NodeList

CSS Selectors in JavaScript

querySelector() and querySelectorAll() support CSS selectors, making them flexible for selecting elements based on IDs, classes, attributes, relationships, and other conditions.

CSS Selector Examples
// ID
document.querySelector(
    '#title'
);


// Class
document.querySelector(
    '.card'
);


// Element
document.querySelector(
    'button'
);


// Attribute
document.querySelector(
    '[data-id]'
);


// Specific attribute value
document.querySelector(
    '[type="email"]'
);


// Descendant
document.querySelector(
    '.card p'
);


// Direct child
document.querySelector(
    '.menu > li'
);


// Multiple selectors
document.querySelectorAll(
    'h1, h2, h3'
);


// Pseudo-class
document.querySelector(
    'li:first-child'
);

Changing HTML Content

After selecting an element, JavaScript can read or change its content using properties such as textContent, innerText, and innerHTML.

textContent

The textContent property reads or replaces the text content of an element and its descendants.

index.html
<h1 id="title">
    Old Title
</h1>
Change Text Content
const title =
    document.getElementById(
        'title'
    );

title.textContent =
    'JavaScript DOM';
Browser Output
Read Text Content
const title =
    document.getElementById(
        'title'
    );

console.log(
    title.textContent
);

innerText

The innerText property represents the rendered visible text of an element. It considers styling and layout when determining visible text.

index.html
<div id="box">
    Visible Text

    <span style="display: none;">
        Hidden Text
    </span>
</div>
textContent vs innerText
const box =
    document.getElementById(
        'box'
    );

console.log(
    box.textContent
);

console.log(
    box.innerText
);

textContent includes text from hidden descendants, while innerText focuses on rendered visible text.

innerHTML

The innerHTML property reads or replaces the HTML markup inside an element.

index.html
<div id="container">
    Original Content
</div>
Insert HTML Content
const container =
    document.getElementById(
        'container'
    );

container.innerHTML = `
    <h2>New Heading</h2>

    <p>
        New paragraph content.
    </p>
`;
Browser Output
Be Careful with innerHTML
  • innerHTML parses strings as HTML.
  • Do not insert untrusted user input directly with innerHTML.
  • Unsafe HTML insertion can create security vulnerabilities.
  • Use textContent when you only need plain text.
  • Use createElement() when building structured content safely.

Content Properties Comparison

Content Properties
textContent

✓ Reads text
✓ Writes plain text
✓ Includes hidden text
✓ Does not parse HTML


innerText

✓ Reads rendered text
✓ Writes plain text
✓ Considers visibility
✓ May trigger layout calculation


innerHTML

✓ Reads HTML markup
✓ Writes HTML markup
✓ Parses HTML strings
⚠ Requires care with untrusted content

Reading Element Content

index.html
<article id="article">
    <h2>DOM Basics</h2>

    <p>
        Learn the Document Object Model.
    </p>
</article>
Read Content
const article =
    document.getElementById(
        'article'
    );

console.log(
    article.textContent
);

console.log(
    article.innerText
);

console.log(
    article.innerHTML
);

Changing Attributes

HTML elements can contain attributes such as id, class, src, href, title, alt, disabled, and data attributes. JavaScript can read, create, update, and remove these attributes.

getAttribute()

index.html
<a
    id="website"
    href="https://example.com"
    title="Visit Website"
>
    Visit
</a>
Read Attributes
const website =
    document.getElementById(
        'website'
    );

console.log(
    website.getAttribute(
        'href'
    )
);

console.log(
    website.getAttribute(
        'title'
    )
);
Output

setAttribute()

Set Attributes
const image =
    document.querySelector(
        '#profileImage'
    );

image.setAttribute(
    'src',
    'profile.jpg'
);

image.setAttribute(
    'alt',
    'User Profile'
);

hasAttribute()

The hasAttribute() method checks whether an element contains a specified attribute.

Check Attribute
const input =
    document.querySelector(
        'input'
    );

console.log(
    input.hasAttribute(
        'required'
    )
);
Possible Output

removeAttribute()

index.html
<button
    id="submitButton"
    disabled
>
    Submit
</button>
Remove Attribute
const button =
    document.getElementById(
        'submitButton'
    );

button.removeAttribute(
    'disabled'
);

Direct Attribute Properties

Many common HTML attributes can also be accessed through element properties.

Direct Properties
const image =
    document.querySelector(
        'img'
    );

image.src =
    'new-image.jpg';

image.alt =
    'New Image';


const link =
    document.querySelector(
        'a'
    );

link.href =
    'https://example.com';


const input =
    document.querySelector(
        'input'
    );

input.disabled =
    true;

Data Attributes

Custom data attributes store additional information directly on HTML elements. Their names begin with data-.

index.html
<article
    id="course"
    data-course-id="101"
    data-category="javascript"
    data-level="beginner"
>
    JavaScript Course
</article>

dataset

The dataset property provides convenient access to data attributes. Hyphenated names are converted into camelCase property names.

Read Data Attributes
const course =
    document.getElementById(
        'course'
    );

console.log(
    course.dataset.courseId
);

console.log(
    course.dataset.category
);

console.log(
    course.dataset.level
);
Output
Change Data Attributes
const course =
    document.getElementById(
        'course'
    );

course.dataset.level =
    'intermediate';

course.dataset.status =
    'active';
Data Attribute Conversion
HTML

data-course-id="101"

        │
        ▼

JavaScript

element.dataset.courseId


HTML

data-user-role="admin"

        │
        ▼

JavaScript

element.dataset.userRole

Changing Styles

JavaScript can modify an element’s inline CSS styles using the style property.

The style Property

index.html
<div id="box">
    Hello DOM
</div>
Change Styles
const box =
    document.getElementById(
        'box'
    );

box.style.color =
    'white';

box.style.backgroundColor =
    'purple';

box.style.padding =
    '20px';

box.style.borderRadius =
    '10px';

CSS Property Names

CSS properties containing hyphens are normally written in camelCase when accessed through the JavaScript style object.

CSS to JavaScript
CSS

background-color

JavaScript

backgroundColor


CSS

font-size

JavaScript

fontSize


CSS

border-radius

JavaScript

borderRadius


CSS

margin-top

JavaScript

marginTop

Multiple Inline Styles

Change Multiple Styles
const card =
    document.querySelector(
        '.card'
    );

Object.assign(
    card.style,
    {
        padding: '24px',
        borderRadius: '12px',
        backgroundColor: '#222',
        color: 'white'
    }
);
Prefer Classes for Major Visual Changes
  • The style property is useful for dynamic values.
  • CSS classes are usually better for reusable visual states.
  • Keep complex styling in CSS files.
  • Use classList to activate or deactivate those styles.

Reading Computed Styles

The style property mainly represents inline styles. To read the final style applied after CSS rules are calculated, use getComputedStyle().

Read Computed Style
const box =
    document.querySelector(
        '.box'
    );

const styles =
    getComputedStyle(box);

console.log(
    styles.backgroundColor
);

console.log(
    styles.fontSize
);

Working with CSS Classes

CSS classes provide a clean way to define visual states. JavaScript can then add, remove, toggle, check, or replace those classes.

className

index.html
<div
    id="box"
    class="card active"
>
    Content
</div>
Read className
const box =
    document.getElementById(
        'box'
    );

console.log(
    box.className
);
Output
className Replaces the Entire Class String
  • Assigning className replaces existing classes.
  • Use classList when changing individual classes.
  • classList is usually safer for dynamic interfaces.

classList

The classList property provides methods for managing individual CSS classes without replacing the entire class attribute.

Access classList
const box =
    document.querySelector(
        '.box'
    );

console.log(
    box.classList
);

classList.add()

Add Classes
const box =
    document.querySelector(
        '.box'
    );

box.classList.add(
    'active'
);

box.classList.add(
    'highlighted',
    'large'
);

classList.remove()

Remove Classes
const box =
    document.querySelector(
        '.box'
    );

box.classList.remove(
    'active'
);

box.classList.remove(
    'highlighted',
    'large'
);

classList.toggle()

The toggle() method adds a class when it is missing and removes it when it already exists.

Toggle Class
const menu =
    document.querySelector(
        '.menu'
    );

menu.classList.toggle(
    'open'
);
Toggle Behavior
Class Missing

menu
  │
  ▼

toggle('open')

  │
  ▼

menu open


Class Exists

menu open
  │
  ▼

toggle('open')

  │
  ▼

menu

classList.contains()

Check Class
const menu =
    document.querySelector(
        '.menu'
    );

const isOpen =
    menu.classList.contains(
        'open'
    );

console.log(isOpen);

classList.replace()

Replace Class
const message =
    document.querySelector(
        '.message'
    );

message.classList.replace(
    'warning',
    'success'
);

Creating Elements

JavaScript can create completely new HTML elements at runtime. This is essential for displaying data, building lists, creating notifications, adding cards, and updating interfaces dynamically.

createElement()

Create an Element
const paragraph =
    document.createElement(
        'p'
    );

console.log(paragraph);
Console Output

Creating an element does not automatically display it. The new element must be inserted into the document.

Adding Text to Elements

Create Element with Text
const paragraph =
    document.createElement(
        'p'
    );

paragraph.textContent =
    'Created with JavaScript';

console.log(paragraph);
Output

appendChild()

index.html
<div id="container"></div>
Append Child Element
const container =
    document.getElementById(
        'container'
    );

const paragraph =
    document.createElement(
        'p'
    );

paragraph.textContent =
    'New Paragraph';

container.appendChild(
    paragraph
);
Resulting HTML

append()

The append() method can insert multiple nodes and text values at the end of an element.

Append Multiple Items
const container =
    document.querySelector(
        '.container'
    );

const title =
    document.createElement(
        'h2'
    );

title.textContent =
    'DOM Course';

const paragraph =
    document.createElement(
        'p'
    );

paragraph.textContent =
    'Learn JavaScript DOM.';

container.append(
    title,
    paragraph
);

prepend()

The prepend() method inserts nodes or text at the beginning of an element.

Prepend Element
const list =
    document.querySelector(
        'ul'
    );

const item =
    document.createElement(
        'li'
    );

item.textContent =
    'First Item';

list.prepend(item);

before()

The before() method inserts content immediately before an element.

Insert Before Element
const article =
    document.querySelector(
        'article'
    );

const heading =
    document.createElement(
        'h2'
    );

heading.textContent =
    'Article Heading';

article.before(heading);

after()

The after() method inserts content immediately after an element.

Insert After Element
const article =
    document.querySelector(
        'article'
    );

const note =
    document.createElement(
        'p'
    );

note.textContent =
    'End of Article';

article.after(note);

insertAdjacentHTML()

The insertAdjacentHTML() method parses an HTML string and inserts it at a specified position relative to an element.

Insert Adjacent HTML
const container =
    document.querySelector(
        '.container'
    );

container.insertAdjacentHTML(
    'beforeend',
    `
        <div class="card">
            <h3>New Card</h3>

            <p>
                Dynamic content.
            </p>
        </div>
    `
);
Insertion Positions
beforebegin

    ↓

<div class="container">

    afterbegin

        Existing Content

    beforeend

</div>

    ↑

afterend
HTML String Safety
  • insertAdjacentHTML() parses strings as HTML.
  • Do not insert untrusted user input directly.
  • Use createElement() and textContent for safer dynamic content.

Removing Elements

DOM elements can be removed when they are no longer needed.

remove()

Remove Element
const message =
    document.querySelector(
        '.message'
    );

message.remove();

removeChild()

The removeChild() method removes a child node from its parent.

Remove Child
const list =
    document.querySelector(
        'ul'
    );

const firstItem =
    list.firstElementChild;

list.removeChild(
    firstItem
);

Replacing Elements

An existing DOM element can be replaced with another element.

replaceWith()

Replace Element
const oldHeading =
    document.querySelector(
        'h2'
    );

const newHeading =
    document.createElement(
        'h2'
    );

newHeading.textContent =
    'Updated Heading';

oldHeading.replaceWith(
    newHeading
);

Cloning Elements

Existing DOM elements can be copied using cloneNode().

cloneNode()

Clone Element
const card =
    document.querySelector(
        '.card'
    );

const copy =
    card.cloneNode(true);

document.body.append(
    copy
);
Shallow and Deep Cloning
  • cloneNode(false) copies only the selected node.
  • cloneNode(true) copies the node and its descendants.
  • Cloning may duplicate id values.
  • Update unique identifiers when necessary.

DOM Traversal

DOM traversal means moving through the relationships between elements. JavaScript can move from an element to its parent, children, or siblings.

HTML Structure
<section class="course">
    <h2>JavaScript</h2>

    <p>Learn DOM</p>

    <button>Start</button>
</section>
Element Relationships
section.course
      │
      ├── h2
      │
      ├── p
      │
      └── button


section is the PARENT

h2, p, button are CHILDREN

h2, p, button are SIBLINGS

Parent Elements

Access Parent
const button =
    document.querySelector(
        'button'
    );

console.log(
    button.parentElement
);

console.log(
    button.parentNode
);

parentElement returns the parent element, while parentNode returns the parent node, which may not always be an element.

Child Elements

Access Children
const course =
    document.querySelector(
        '.course'
    );

console.log(
    course.children
);

console.log(
    course.firstElementChild
);

console.log(
    course.lastElementChild
);

The children property returns child elements only. firstElementChild and lastElementChild return the first and last child elements.

Sibling Elements

Access Siblings
const paragraph =
    document.querySelector(
        '.course p'
    );

console.log(
    paragraph.previousElementSibling
);

console.log(
    paragraph.nextElementSibling
);

closest()

The closest() method searches the selected element and then moves upward through its ancestors until it finds an element matching a CSS selector.

index.html
<article class="card">
    <div class="content">
        <button class="delete">
            Delete
        </button>
    </div>
</article>
Find Closest Ancestor
const button =
    document.querySelector(
        '.delete'
    );

const card =
    button.closest(
        '.card'
    );

console.log(card);

matches()

The matches() method checks whether an element matches a specified CSS selector.

Check Selector Match
const button =
    document.querySelector(
        'button'
    );

console.log(
    button.matches(
        '.primary'
    )
);

Element Collections

Some DOM selection methods return collections rather than individual elements. Two common collection types are HTMLCollection and NodeList.

HTMLCollection

An HTMLCollection is an array-like collection of elements. Collections returned by methods such as getElementsByClassName() and getElementsByTagName() are live.

HTMLCollection
const items =
    document.getElementsByClassName(
        'item'
    );

console.log(
    items.length
);

console.log(
    items[0]
);

A live collection automatically reflects matching DOM changes.

NodeList

querySelectorAll() returns a static NodeList. The collection does not automatically add new matching elements created after the selection.

NodeList
const items =
    document.querySelectorAll(
        '.item'
    );

items.forEach(
    function (item) {
        console.log(
            item.textContent
        );
    }
);

HTMLCollection vs NodeList

Collection Comparison
HTMLCollection

Common Source:
getElementsByClassName()
getElementsByTagName()

Usually:
Live

Direct forEach():
No

Indexed Access:
Yes


NodeList

Common Source:
querySelectorAll()

Usually:
Static

Direct forEach():
Yes

Indexed Access:
Yes

Looping Through Elements

Loop Through NodeList
const cards =
    document.querySelectorAll(
        '.card'
    );

cards.forEach(
    function (card) {
        console.log(
            card.textContent
        );
    }
);
Loop with for...of
const cards =
    document.querySelectorAll(
        '.card'
    );

for (
    const card
    of cards
) {
    console.log(
        card.textContent
    );
}

Converting Collections to Arrays

Using Array.from()
const collection =
    document.getElementsByClassName(
        'item'
    );

const items =
    Array.from(
        collection
    );

console.log(
    Array.isArray(items)
);
Output
Using Spread Operator
const collection =
    document.getElementsByClassName(
        'item'
    );

const items = [
    ...collection
];

Working with Forms

The DOM allows JavaScript to read and update form controls such as text inputs, checkboxes, radio buttons, and select elements.

Reading Input Values

index.html
<input
    id="username"
    type="text"
    value="Aarav"
>
Read Input Value
const username =
    document.getElementById(
        'username'
    );

console.log(
    username.value
);
Output

Changing Input Values

Change Input Value
const username =
    document.getElementById(
        'username'
    );

username.value =
    'JavaScript Student';

Checkboxes

index.html
<input
    id="terms"
    type="checkbox"
    checked
>
Read Checkbox State
const terms =
    document.getElementById(
        'terms'
    );

console.log(
    terms.checked
);
Output

Radio Buttons

index.html
<label>
    <input
        type="radio"
        name="level"
        value="beginner"
        checked
    >
    Beginner
</label>

<label>
    <input
        type="radio"
        name="level"
        value="advanced"
    >
    Advanced
</label>
Read Selected Radio Value
const selected =
    document.querySelector(
        'input[name="level"]:checked'
    );

console.log(
    selected.value
);
Output

Select Elements

index.html
<select id="language">
    <option value="javascript">
        JavaScript
    </option>

    <option value="java">
        Java
    </option>

    <option value="python">
        Python
    </option>
</select>
Read Selected Value
const language =
    document.getElementById(
        'language'
    );

console.log(
    language.value
);
Output

Form Elements Collection

index.html
<form id="profileForm">
    <input
        name="username"
        value="Aarav"
    >

    <input
        name="email"
        value="aarav@example.com"
    >
</form>
Access Form Controls
const form =
    document.getElementById(
        'profileForm'
    );

console.log(
    form.elements.username.value
);

console.log(
    form.elements.email.value
);

Element Dimensions

The DOM provides properties for measuring element dimensions. Different properties include different parts of the CSS box model.

offsetWidth and offsetHeight

offsetWidth and offsetHeight include the content, padding, border, and scrollbar when present.

Read Offset Dimensions
const box =
    document.querySelector(
        '.box'
    );

console.log(
    box.offsetWidth
);

console.log(
    box.offsetHeight
);

clientWidth and clientHeight

clientWidth and clientHeight include the content and padding but exclude borders.

Read Client Dimensions
console.log(
    box.clientWidth
);

console.log(
    box.clientHeight
);

scrollWidth and scrollHeight

scrollWidth and scrollHeight represent the full size of the content, including content that is currently outside the visible area because of scrolling.

Read Scroll Dimensions
console.log(
    box.scrollWidth
);

console.log(
    box.scrollHeight
);
Dimension Comparison
offsetWidth / offsetHeight

Content
+ Padding
+ Border
+ Scrollbar


clientWidth / clientHeight

Content
+ Padding


scrollWidth / scrollHeight

Full Scrollable Content
+ Padding

Element Position

JavaScript can determine the size and position of an element relative to the browser viewport.

getBoundingClientRect()

Read Element Position
const card =
    document.querySelector(
        '.card'
    );

const rectangle =
    card.getBoundingClientRect();

console.log(
    rectangle.top
);

console.log(
    rectangle.left
);

console.log(
    rectangle.width
);

console.log(
    rectangle.height
);

The returned object also contains values such as right, bottom, x, and y.

Scrolling Elements

The DOM provides methods for moving elements into the visible viewport.

scrollIntoView()

Scroll to Element
const section =
    document.getElementById(
        'summary'
    );

section.scrollIntoView({
    behavior: 'smooth',
    block: 'start'
});

Document Ready State

JavaScript can only select elements that the browser has already parsed. Script placement and loading strategy therefore affect DOM access.

Check Ready State
console.log(
    document.readyState
);
Ready State Values
loading

The document is still loading.


interactive

HTML has been parsed.


complete

The document and resources
have finished loading.

Script Loading

Recommended External Script
<script
    src="script.js"
    defer
></script>

The defer attribute allows the script to download without blocking HTML parsing and executes it after the HTML has been parsed.

DOMContentLoaded Alternative
document.addEventListener(
    'DOMContentLoaded',
    function () {
        const title =
            document.getElementById(
                'title'
            );

        console.log(title);
    }
);
Recommended Script Loading
  • Use defer for traditional external scripts that need the DOM.
  • Place scripts carefully when defer is not used.
  • Make sure elements exist before selecting them.
  • Handle null when an element may not exist.

Complete DOM Example

The following example creates a dynamic task manager. Users can add tasks, mark tasks as completed, delete tasks, filter tasks, and view live statistics. The example focuses on DOM selection, creation, content updates, classes, attributes, traversal, and removal.

index.html
<div class="task-app">
    <header class="task-header">
        <p class="eyebrow">
            JavaScript DOM Project
        </p>

        <h2>
            Task Manager
        </h2>

        <p>
            Create and manage tasks dynamically.
        </p>
    </header>

    <div class="task-form">
        <input
            id="taskInput"
            type="text"
            placeholder="Enter a new task"
        >

        <select id="priorityInput">
            <option value="low">
                Low Priority
            </option>

            <option value="medium">
                Medium Priority
            </option>

            <option value="high">
                High Priority
            </option>
        </select>

        <button id="addTaskButton">
            Add Task
        </button>
    </div>

    <div class="task-filters">
        <button
            class="filter-button active"
            data-filter="all"
        >
            All
        </button>

        <button
            class="filter-button"
            data-filter="pending"
        >
            Pending
        </button>

        <button
            class="filter-button"
            data-filter="completed"
        >
            Completed
        </button>
    </div>

    <div
        id="message"
        class="task-message"
    >
        Add your first task.
    </div>

    <ul id="taskList"></ul>

    <div class="task-stats">
        <div>
            <span>Total</span>
            <strong id="totalCount">
                0
            </strong>
        </div>

        <div>
            <span>Pending</span>
            <strong id="pendingCount">
                0
            </strong>
        </div>

        <div>
            <span>Completed</span>
            <strong id="completedCount">
                0
            </strong>
        </div>
    </div>
</div>
style.css
.task-app {
    max-width: 760px;
    margin: 40px auto;
    padding: 28px;
    border-radius: 18px;
    background: var(--bg-secondary);
}

.task-header {
    margin-bottom: 24px;
}

.eyebrow {
    margin-bottom: 8px;
    color: var(--accent-light);
    font-size: 0.8rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.08em;
}

.task-form {
    display: grid;
    grid-template-columns: 1fr auto auto;
    gap: 10px;
    margin-bottom: 18px;
}

.task-form input,
.task-form select,
.task-form button {
    padding: 12px 14px;
    border-radius: 10px;
}

.task-filters {
    display: flex;
    gap: 8px;
    margin-bottom: 18px;
}

.filter-button {
    padding: 8px 14px;
    border: none;
    border-radius: 50px;
    cursor: pointer;
}

.filter-button.active {
    background: var(--accent);
    color: white;
}

.task-message {
    margin-bottom: 14px;
    color: var(--text-secondary);
}

#taskList {
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding: 0;
    list-style: none;
}

.task-item {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 14px;
    border: 1px solid var(--border-color);
    border-radius: 12px;
}

.task-content {
    flex: 1;
}

.task-title {
    margin: 0 0 4px;
}

.task-priority {
    font-size: 0.75rem;
    color: var(--text-secondary);
}

.task-item.completed .task-title {
    text-decoration: line-through;
    opacity: 0.6;
}

.task-actions {
    display: flex;
    gap: 8px;
}

.task-actions button {
    padding: 7px 10px;
    border: none;
    border-radius: 8px;
    cursor: pointer;
}

.task-stats {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 10px;
    margin-top: 20px;
}

.task-stats div {
    padding: 14px;
    border-radius: 12px;
    background: var(--bg-primary);
}

.task-stats span,
.task-stats strong {
    display: block;
}

.task-stats span {
    margin-bottom: 6px;
    font-size: 0.8rem;
    color: var(--text-secondary);
}
script.js
const taskInput =
    document.getElementById(
        'taskInput'
    );

const priorityInput =
    document.getElementById(
        'priorityInput'
    );

const addTaskButton =
    document.getElementById(
        'addTaskButton'
    );

const taskList =
    document.getElementById(
        'taskList'
    );

const message =
    document.getElementById(
        'message'
    );

const totalCount =
    document.getElementById(
        'totalCount'
    );

const pendingCount =
    document.getElementById(
        'pendingCount'
    );

const completedCount =
    document.getElementById(
        'completedCount'
    );

const filterButtons =
    document.querySelectorAll(
        '.filter-button'
    );


let currentFilter = 'all';


addTaskButton.addEventListener(
    'click',
    addTask
);


taskInput.addEventListener(
    'keydown',
    function (event) {
        if (
            event.key === 'Enter'
        ) {
            addTask();
        }
    }
);


filterButtons.forEach(
    function (button) {
        button.addEventListener(
            'click',
            function () {
                currentFilter =
                    button.dataset.filter;

                updateActiveFilter(
                    button
                );

                filterTasks();
            }
        );
    }
);


function addTask() {
    const title =
        taskInput.value.trim();

    const priority =
        priorityInput.value;


    if (title === '') {
        showMessage(
            'Enter a task before adding it.'
        );

        taskInput.focus();

        return;
    }


    const taskItem =
        createTaskElement(
            title,
            priority
        );


    taskList.append(
        taskItem
    );


    taskInput.value = '';

    taskInput.focus();


    showMessage(
        'Task added successfully.'
    );

    updateStatistics();

    filterTasks();
}


function createTaskElement(
    title,
    priority
) {
    const taskItem =
        document.createElement(
            'li'
        );

    taskItem.classList.add(
        'task-item'
    );

    taskItem.dataset.status =
        'pending';


    const content =
        document.createElement(
            'div'
        );

    content.classList.add(
        'task-content'
    );


    const taskTitle =
        document.createElement(
            'h3'
        );

    taskTitle.classList.add(
        'task-title'
    );

    taskTitle.textContent =
        title;


    const priorityText =
        document.createElement(
            'span'
        );

    priorityText.classList.add(
        'task-priority'
    );

    priorityText.textContent =
        `${priority} priority`;


    content.append(
        taskTitle,
        priorityText
    );


    const actions =
        document.createElement(
            'div'
        );

    actions.classList.add(
        'task-actions'
    );


    const completeButton =
        document.createElement(
            'button'
        );

    completeButton.type =
        'button';

    completeButton.textContent =
        'Complete';

    completeButton.classList.add(
        'complete-button'
    );


    const deleteButton =
        document.createElement(
            'button'
        );

    deleteButton.type =
        'button';

    deleteButton.textContent =
        'Delete';

    deleteButton.classList.add(
        'delete-button'
    );


    completeButton.addEventListener(
        'click',
        function () {
            toggleTask(
                taskItem,
                completeButton
            );
        }
    );


    deleteButton.addEventListener(
        'click',
        function () {
            taskItem.remove();

            showMessage(
                'Task deleted.'
            );

            updateStatistics();

            filterTasks();
        }
    );


    actions.append(
        completeButton,
        deleteButton
    );


    taskItem.append(
        content,
        actions
    );


    return taskItem;
}


function toggleTask(
    taskItem,
    button
) {
    const isCompleted =
        taskItem.classList.toggle(
            'completed'
        );


    if (isCompleted) {
        taskItem.dataset.status =
            'completed';

        button.textContent =
            'Undo';

        showMessage(
            'Task completed.'
        );
    } else {
        taskItem.dataset.status =
            'pending';

        button.textContent =
            'Complete';

        showMessage(
            'Task moved back to pending.'
        );
    }


    updateStatistics();

    filterTasks();
}


function updateActiveFilter(
    activeButton
) {
    filterButtons.forEach(
        function (button) {
            button.classList.remove(
                'active'
            );
        }
    );


    activeButton.classList.add(
        'active'
    );
}


function filterTasks() {
    const tasks =
        taskList.querySelectorAll(
            '.task-item'
        );


    tasks.forEach(
        function (task) {
            const status =
                task.dataset.status;


            const shouldShow =
                currentFilter === 'all'
                ||
                currentFilter === status;


            task.hidden =
                !shouldShow;
        }
    );
}


function updateStatistics() {
    const tasks =
        taskList.querySelectorAll(
            '.task-item'
        );

    const completedTasks =
        taskList.querySelectorAll(
            '.task-item.completed'
        );

    const total =
        tasks.length;

    const completed =
        completedTasks.length;

    const pending =
        total - completed;


    totalCount.textContent =
        total;

    pendingCount.textContent =
        pending;

    completedCount.textContent =
        completed;
}


function showMessage(text) {
    message.textContent =
        text;
}
Browser Output
What This Example Demonstrates
  • Selecting elements by ID.
  • Selecting multiple elements with querySelectorAll().
  • Reading input values.
  • Removing extra whitespace with trim().
  • Validating empty input.
  • Creating elements with createElement().
  • Adding plain text with textContent.
  • Adding CSS classes with classList.add().
  • Toggling CSS classes with classList.toggle().
  • Removing CSS classes with classList.remove().
  • Using custom data attributes.
  • Reading data attributes with dataset.
  • Appending multiple elements.
  • Removing elements with remove().
  • Selecting descendants from a specific element.
  • Updating text dynamically.
  • Using the hidden property.
  • Updating live statistics.
  • Filtering DOM elements.
  • Creating reusable functions.
  • Combining DOM manipulation with events.
  • Building a complete dynamic interface.

DOM Processing Flow

DOM Processing Flow
HTML DOCUMENT
      │
      ▼
┌──────────────────────────────┐
│ BROWSER PARSES HTML          │
│                              │
│ Creates DOM Tree             │
└──────────────┬───────────────┘
               │
               ▼
┌──────────────────────────────┐
│ SELECT                       │
│                              │
│ getElementById()             │
│ querySelector()              │
│ querySelectorAll()           │
└──────────────┬───────────────┘
               │
               ▼
┌──────────────────────────────┐
│ READ                         │
│                              │
│ textContent                  │
│ value                        │
│ attributes                   │
│ dataset                      │
└──────────────┬───────────────┘
               │
               ▼
┌──────────────────────────────┐
│ PROCESS                      │
│                              │
│ Conditions                   │
│ Functions                    │
│ Arrays                       │
│ Objects                      │
└──────────────┬───────────────┘
               │
               ▼
┌──────────────────────────────┐
│ MODIFY                       │
│                              │
│ Content                      │
│ Attributes                   │
│ Classes                      │
│ Styles                       │
└──────────────┬───────────────┘
               │
               ▼
┌──────────────────────────────┐
│ CREATE OR REMOVE             │
│                              │
│ createElement()              │
│ append()                     │
│ remove()                     │
└──────────────┬───────────────┘
               │
               ▼
┌──────────────────────────────┐
│ BROWSER UPDATES PAGE         │
│                              │
│ User sees new interface      │
└──────────────────────────────┘

Real-World Applications

Form Validation

Read inputs and display validation messages dynamically.

Shopping Carts

Create, update, and remove cart items.

Task Managers

Add, complete, filter, and delete tasks.

Notifications

Create alerts, toast messages, and status indicators.

Dashboards

Update statistics, cards, tables, and charts.

Search Interfaces

Filter visible elements based on user input.

Theme Switchers

Toggle classes to change light and dark themes.

Navigation Menus

Open and close responsive menus.

Modals

Show and hide dialogs and overlays.

Accordions

Expand and collapse content sections.

Tabs

Switch visible content based on selected tabs.

Dynamic Content

Convert JavaScript and API data into HTML elements.

Common Beginner Mistakes

Avoid These Mistakes
  • Confusing the DOM with HTML source code.
  • Assuming DOM changes automatically modify the original HTML file.
  • Trying to select elements before the browser has parsed them.
  • Forgetting to use defer when appropriate.
  • Using the wrong element ID.
  • Including # inside getElementById().
  • Forgetting # when selecting an ID with querySelector().
  • Forgetting . when selecting a class with querySelector().
  • Expecting getElementById() to return multiple elements.
  • Expecting querySelector() to return all matching elements.
  • Forgetting that querySelector() returns only the first match.
  • Forgetting that querySelectorAll() returns a collection.
  • Trying to use textContent directly on a NodeList.
  • Forgetting to loop through multiple selected elements.
  • Assuming every selector always finds an element.
  • Ignoring the possibility of null.
  • Trying to access a property of null.
  • Using innerHTML when only plain text is required.
  • Inserting untrusted user input with innerHTML.
  • Inserting untrusted content with insertAdjacentHTML().
  • Confusing textContent and innerHTML.
  • Expecting HTML tags inside textContent to render as HTML.
  • Expecting innerText and textContent to always return identical values.
  • Using className when only one class should change.
  • Accidentally replacing all classes with className.
  • Forgetting that classList.add() requires class names without dots.
  • Writing classList.add(".active") instead of classList.add("active").
  • Writing classList.remove(".active") with a dot.
  • Forgetting that toggle() can both add and remove a class.
  • Changing many styles directly instead of using CSS classes.
  • Using CSS hyphenated property names directly with dot notation.
  • Writing element.style.background-color.
  • Expecting element.style to return every applied CSS rule.
  • Forgetting to use getComputedStyle() for final computed styles.
  • Using Math or string operations on input values without conversion.
  • Forgetting that input.value returns a string.
  • Reading checkbox value when checked state is required.
  • Using value instead of checked for checkboxes.
  • Forgetting :checked when selecting the selected radio button.
  • Creating an element but forgetting to insert it into the document.
  • Calling createElement() and expecting immediate browser output.
  • Appending an element to the wrong parent.
  • Confusing append() and appendChild().
  • Forgetting that appendChild() accepts one node.
  • Removing an element before confirming that it exists.
  • Using removeChild() with an element that is not a child of the selected parent.
  • Cloning elements without considering duplicate IDs.
  • Using cloneNode(false) when child content is also required.
  • Confusing childNodes with children.
  • Confusing firstChild with firstElementChild.
  • Forgetting that whitespace can create text nodes.
  • Using parentNode when specifically expecting an element.
  • Traversing too many levels with repeated parentElement calls.
  • Ignoring closest() for ancestor searches.
  • Assuming closest() always returns an element.
  • Forgetting that closest() can return null.
  • Confusing HTMLCollection and NodeList.
  • Assuming every DOM collection supports forEach().
  • Assuming every DOM collection is a real array.
  • Trying to use array methods directly on an HTMLCollection.
  • Forgetting that some HTMLCollections are live.
  • Modifying a live collection while looping through it without understanding the effect.
  • Assuming querySelectorAll() automatically updates after new elements are added.
  • Reading dimensions before an element is rendered.
  • Confusing offsetWidth, clientWidth, and scrollWidth.
  • Assuming getBoundingClientRect() returns document coordinates.
  • Forgetting that its position is relative to the viewport.
  • Using repeated DOM queries unnecessarily.
  • Selecting the same static element many times.
  • Creating excessive DOM updates inside large loops.
  • Mixing data processing and DOM manipulation everywhere.
  • Using unclear variable names such as x or el for important elements.
  • Creating duplicate IDs dynamically.
  • Forgetting accessibility when dynamically creating buttons or controls.
  • Using clickable div elements when a button is appropriate.
  • Changing only visual state without updating meaningful element state.
  • Failing to test the page when expected elements are missing.
Common DOM Mistakes
// ❌ Wrong
document.getElementById(
    '#title'
);


// ✅ Correct
document.getElementById(
    'title'
);


// ❌ Wrong
document.querySelector(
    'title'
);


// ✅ Select ID
document.querySelector(
    '#title'
);


// ❌ Wrong
const items =
    document.querySelectorAll(
        '.item'
    );

// items.textContent = 'Updated';


// ✅ Correct
items.forEach(
    function (item) {
        item.textContent =
            'Updated';
    }
);


// ❌ Wrong class name
element.classList.add(
    '.active'
);


// ✅ Correct
element.classList.add(
    'active'
);


// ❌ HTML input value is a string
const total =
    firstInput.value
    +
    secondInput.value;


// ✅ Convert first
const total =
    Number(firstInput.value)
    +
    Number(secondInput.value);


// ❌ Element may not exist
// document.querySelector(
//     '.unknown'
// ).textContent = 'Hello';


// ✅ Check first
const element =
    document.querySelector(
        '.unknown'
    );

if (element) {
    element.textContent =
        'Hello';
}

Best Practices

  • Understand the DOM as a browser-created object representation of the document.
  • Use descriptive variable names for selected elements.
  • Use const for element references that are not reassigned.
  • Use getElementById() for direct unique ID selection when appropriate.
  • Use querySelector() for flexible single-element selection.
  • Use querySelectorAll() for flexible multiple-element selection.
  • Use valid CSS selectors with querySelector methods.
  • Remember that querySelector() returns only the first match.
  • Remember that querySelectorAll() returns a NodeList.
  • Check whether optional elements exist before using them.
  • Handle null when a selector may not find a match.
  • Cache frequently used static element references.
  • Avoid repeating identical DOM queries unnecessarily.
  • Use textContent for plain text.
  • Use innerHTML only when HTML parsing is actually required.
  • Never insert untrusted user input directly with innerHTML.
  • Never insert untrusted user input directly with insertAdjacentHTML().
  • Prefer createElement() and textContent for dynamic user-controlled content.
  • Use getAttribute() when the exact attribute value is needed.
  • Use setAttribute() for general attribute updates.
  • Use direct properties for common states such as value, checked, and disabled.
  • Use data attributes for element-specific custom information.
  • Use dataset for convenient access to data attributes.
  • Use camelCase when accessing hyphenated data attributes through dataset.
  • Use the style property for truly dynamic inline values.
  • Prefer CSS classes for reusable visual states.
  • Use classList instead of replacing the entire className when changing individual classes.
  • Use classList.add() to add classes.
  • Use classList.remove() to remove classes.
  • Use classList.toggle() for two-state interfaces.
  • Use classList.contains() when state checking is required.
  • Use getComputedStyle() when reading final applied styles.
  • Use createElement() to create structured elements.
  • Set text with textContent.
  • Set necessary properties and attributes before insertion.
  • Use append() when inserting multiple nodes.
  • Use prepend() when inserting content at the beginning.
  • Use before() and after() for sibling insertion.
  • Use remove() for straightforward element removal.
  • Use cloneNode(true) only when descendant content should also be copied.
  • Avoid duplicate IDs when cloning elements.
  • Use children when you need element children only.
  • Use firstElementChild and lastElementChild to avoid text-node confusion.
  • Use previousElementSibling and nextElementSibling for element traversal.
  • Use closest() for ancestor searches.
  • Check the result of closest() when a matching ancestor may not exist.
  • Understand whether a collection is live or static.
  • Use forEach() with NodeLists returned by querySelectorAll().
  • Use for...of when it improves clarity.
  • Convert collections to arrays when array methods are required.
  • Remember that HTML input values are strings.
  • Convert input values before numeric calculations.
  • Use checked for checkbox and radio state.
  • Use value for text inputs and select elements.
  • Use meaningful HTML elements when creating interactive controls.
  • Preserve accessibility when modifying the DOM.
  • Avoid excessive DOM updates inside large loops.
  • Create elements in memory before inserting them when practical.
  • Separate data logic from rendering logic.
  • Create reusable rendering functions.
  • Create reusable element factory functions when many similar elements are needed.
  • Use data attributes to connect elements with application data when appropriate.
  • Use defer for external scripts that depend on parsed HTML.
  • Test DOM code when elements exist.
  • Test DOM code when optional elements are missing.
  • Test empty collections.
  • Test dynamically added elements.
  • Test dynamically removed elements.
  • Test keyboard accessibility.
  • Test different screen sizes.
  • Keep DOM manipulation clear and predictable.

Frequently Asked Questions

What does DOM stand for?

DOM stands for Document Object Model.

What is the DOM?

The DOM is a browser-created object representation of an HTML document.

Is the DOM the same as HTML?

No. HTML is source markup, while the DOM is the object structure created from the document.

Who creates the DOM?

The browser creates the DOM when it parses the HTML document.

Why does JavaScript need the DOM?

The DOM gives JavaScript a standard way to access and modify the web page.

What is a DOM tree?

It is the hierarchical structure of nodes representing the document.

What is a DOM node?

A node is an item in the DOM tree, such as a document, element, text, or comment node.

What is the document object?

It is the main JavaScript object representing the loaded HTML document.

How do I select an element by ID?

Use document.getElementById() or a CSS ID selector with querySelector().

Should I include # in getElementById()?

No. Pass only the ID value.

Should I include # in querySelector() for an ID?

Yes, because querySelector() uses CSS selector syntax.

How do I select elements by class?

Use getElementsByClassName() or querySelectorAll() with a class selector.

What does querySelector() return?

The first matching element or null.

What does querySelectorAll() return?

A static NodeList containing all matching elements.

What happens when querySelector() finds nothing?

It returns null.

Can querySelector() use CSS selectors?

Yes. It accepts valid CSS selectors.

How do I change text?

Select the element and assign a new value to textContent or innerText.

What is the difference between textContent and innerHTML?

textContent handles plain text, while innerHTML reads or parses HTML markup.

What is the difference between textContent and innerText?

textContent represents textual content including hidden descendants, while innerText focuses on rendered visible text.

Is innerHTML safe?

It can be safe with trusted content, but inserting untrusted input directly can create security vulnerabilities.

How do I read an attribute?

Use getAttribute() or an appropriate element property.

How do I change an attribute?

Use setAttribute() or an appropriate element property.

How do I remove an attribute?

Use removeAttribute().

How do I check whether an attribute exists?

Use hasAttribute().

What are data attributes?

They are custom HTML attributes beginning with data- that store additional element information.

How do I access data attributes?

Use the dataset property.

How does data-user-id appear in dataset?

It becomes dataset.userId.

How do I change an inline style?

Use the element style property.

How do I write background-color in JavaScript style syntax?

Use backgroundColor.

How do I read the final applied CSS style?

Use getComputedStyle().

How do I add a CSS class?

Use classList.add().

How do I remove a CSS class?

Use classList.remove().

How do I toggle a CSS class?

Use classList.toggle().

How do I check whether an element has a class?

Use classList.contains().

How do I replace one class with another?

Use classList.replace().

Should class names passed to classList include a dot?

No. Pass the class name without the CSS selector dot.

How do I create an HTML element?

Use document.createElement().

Does createElement() automatically display the element?

No. The element must be inserted into the document.

How do I add an element to the end of a parent?

Use append(), appendChild(), or another insertion method.

What is the difference between append() and appendChild()?

append() can accept multiple nodes and strings, while appendChild() accepts one node.

How do I add content at the beginning of an element?

Use prepend().

How do I insert content before an element?

Use before().

How do I insert content after an element?

Use after().

How do I remove an element?

Use remove().

How do I replace an element?

Use replaceWith().

How do I copy an element?

Use cloneNode().

What does cloneNode(true) do?

It creates a deep clone including descendant nodes.

What does cloneNode(false) do?

It copies only the selected node without descendants.

What is DOM traversal?

DOM traversal means navigating between related nodes or elements.

How do I access a parent element?

Use parentElement.

How do I access child elements?

Use children.

How do I access the first child element?

Use firstElementChild.

How do I access the last child element?

Use lastElementChild.

How do I access the next sibling element?

Use nextElementSibling.

How do I access the previous sibling element?

Use previousElementSibling.

What does closest() do?

It searches the element and its ancestors for the nearest element matching a CSS selector.

What does matches() do?

It checks whether an element matches a CSS selector.

What is an HTMLCollection?

It is an array-like collection of elements, often live.

What is a NodeList?

It is an array-like collection of nodes. querySelectorAll() returns a static NodeList.

Is an HTMLCollection an array?

No.

Is a NodeList an array?

No.

How do I convert a DOM collection into an array?

Use Array.from() or the spread operator when supported by the collection.

Are HTML input values numbers?

No. The value property returns a string.

How do I read a checkbox state?

Use the checked property.

How do I read a selected radio button?

Select the checked radio input and read its value.

How do I read a select value?

Use the value property of the select element.

What does offsetWidth include?

It includes content, padding, border, and scrollbar when present.

What does clientWidth include?

It includes content and padding but excludes borders.

What does scrollWidth represent?

It represents the full width of scrollable content.

How do I find an element position?

Use getBoundingClientRect().

What is getBoundingClientRect() relative to?

Its position values are relative to the viewport.

How do I smoothly scroll to an element?

Use scrollIntoView() with behavior set to smooth.

Why does my selector return null?

The selector may be incorrect, the element may not exist, or the script may run before the element is parsed.

What does the defer attribute do?

It allows an external script to download without blocking HTML parsing and executes it after parsing is complete.

Does changing the DOM change the original HTML file?

No. It changes the current in-memory document displayed by the browser.

Key Takeaways

  • DOM stands for Document Object Model.
  • The browser creates the DOM from the HTML document.
  • The DOM represents the document as a tree of objects.
  • Everything in the DOM is represented through nodes.
  • The document object is the main entry point to the DOM.
  • getElementById() selects an element by ID.
  • getElementsByClassName() returns a live HTMLCollection.
  • getElementsByTagName() returns a live HTMLCollection.
  • querySelector() returns the first CSS selector match.
  • querySelectorAll() returns a static NodeList.
  • Selectors can return null when no element matches.
  • textContent reads and writes plain text.
  • innerText focuses on rendered visible text.
  • innerHTML reads and writes HTML markup.
  • Untrusted input should not be inserted directly with innerHTML.
  • getAttribute() reads attributes.
  • setAttribute() creates or updates attributes.
  • hasAttribute() checks attribute existence.
  • removeAttribute() removes attributes.
  • dataset provides access to data attributes.
  • The style property changes inline styles.
  • getComputedStyle() reads final calculated styles.
  • classList manages individual CSS classes.
  • classList.add() adds classes.
  • classList.remove() removes classes.
  • classList.toggle() switches class state.
  • classList.contains() checks class existence.
  • classList.replace() replaces a class.
  • createElement() creates new elements.
  • Created elements must be inserted into the document.
  • appendChild() adds one child node.
  • append() can add multiple nodes and strings.
  • prepend() inserts content at the beginning.
  • before() and after() insert siblings.
  • remove() deletes an element.
  • replaceWith() replaces an element.
  • cloneNode() copies an element.
  • DOM traversal moves through element relationships.
  • parentElement accesses an element parent.
  • children accesses child elements.
  • Sibling properties move between related elements.
  • closest() finds a matching ancestor.
  • matches() checks a CSS selector match.
  • HTMLCollection and NodeList are array-like but are not arrays.
  • Some DOM collections are live while others are static.
  • Input values are strings.
  • Checkbox and radio state is read with checked.
  • Element dimensions can be measured through DOM properties.
  • getBoundingClientRect() returns size and viewport position.
  • scrollIntoView() can move an element into the viewport.
  • Scripts must run after required elements are available.
  • The defer attribute is useful for DOM-dependent external scripts.
  • DOM manipulation is the foundation of interactive web interfaces.

Summary

The Document Object Model is the connection between JavaScript and the visible HTML document. The browser converts HTML into a structured tree of objects that JavaScript can access and modify.

The document object provides methods such as getElementById(), querySelector(), and querySelectorAll() for finding elements.

Properties such as textContent, innerText, and innerHTML allow JavaScript to read and change element content. Each property serves a different purpose, and plain text should normally use textContent.

Attributes can be managed using getAttribute(), setAttribute(), hasAttribute(), and removeAttribute(). Custom data attributes can be accessed conveniently through dataset.

The style property allows inline style changes, while classList provides a cleaner approach for reusable visual states through CSS classes.

JavaScript can create new elements with createElement(), add content, insert elements using append(), prepend(), before(), and after(), and remove elements when they are no longer required.

DOM traversal allows JavaScript to move through parent, child, sibling, and ancestor relationships. Methods such as closest() make it easier to find related elements.

DOM collections such as HTMLCollection and NodeList represent groups of elements. Understanding whether a collection is live or static is important when the document changes dynamically.

Forms, element dimensions, positions, scrolling, and document loading can all be controlled through DOM APIs.

Mastering the DOM allows you to build dynamic forms, task managers, shopping carts, menus, tabs, modals, notifications, dashboards, filters, theme switchers, and other interactive web interfaces.

Lesson 21 Completed
  • You understand what the DOM is.
  • You understand why JavaScript needs the DOM.
  • You understand how HTML becomes a DOM tree.
  • You understand DOM nodes.
  • You know the main node types.
  • You understand the document object.
  • You can select elements by ID.
  • You can select elements by class.
  • You can select elements by tag name.
  • You can use querySelector().
  • You can use querySelectorAll().
  • You can use CSS selectors in JavaScript.
  • You can read and change text content.
  • You understand textContent.
  • You understand innerText.
  • You understand innerHTML.
  • You can read attributes.
  • You can create and update attributes.
  • You can check attributes.
  • You can remove attributes.
  • You can work with data attributes.
  • You can use dataset.
  • You can change inline styles.
  • You can read computed styles.
  • You can manage CSS classes.
  • You can add classes.
  • You can remove classes.
  • You can toggle classes.
  • You can check classes.
  • You can replace classes.
  • You can create new elements.
  • You can add text to elements.
  • You can append elements.
  • You can prepend elements.
  • You can insert siblings.
  • You can remove elements.
  • You can replace elements.
  • You can clone elements.
  • You can traverse the DOM.
  • You can access parents.
  • You can access children.
  • You can access siblings.
  • You can use closest().
  • You can use matches().
  • You understand HTMLCollection.
  • You understand NodeList.
  • You can loop through selected elements.
  • You can convert collections into arrays.
  • You can read form values.
  • You can work with checkboxes.
  • You can work with radio buttons.
  • You can work with select elements.
  • You can measure element dimensions.
  • You can find element positions.
  • You can scroll elements into view.
  • You understand document loading.
  • You can build a complete dynamic DOM application.
  • You are ready to learn JavaScript Events.
Next Lesson →

JavaScript Events