Web Development /JavaScript Programming / Lesson
Web Development

JavaScript DOM Fundamentals and Selecting Elements

Learn how JavaScript interacts with the Document Object Model (DOM), how HTML documents are represented as objects, and how to select and work with elements using modern DOM selection methods.

🎯

Learning Objectives

["Understand what the Document Object Model (DOM) is and how it represents an HTML document.","Explain the relationship between HTML, the DOM and JavaScript.","Understand DOM nodes, elements, parents, children and siblings.","Select HTML elements using getElementById().","Select elements using getElementsByClassName().","Select elements using getElementsByTagName().","Use querySelector() to select individual elements.","Use querySelectorAll() to select multiple elements.","Understand the difference between HTMLCollections and NodeLists.","Navigate between selected elements and their relationships.","Use DOM selection safely when JavaScript loads before or after the HTML.","Build practical JavaScript features by connecting HTML elements to JavaScript."]

📖

Lesson Content

Introduction

JavaScript becomes especially powerful in web development when it can interact with the HTML document displayed in the browser. The technology that makes this interaction possible is called the Document Object Model (DOM).

The DOM provides JavaScript with a structured representation of an HTML document. JavaScript can use this representation to find elements, read their content, change their attributes, modify styles, create new elements, remove elements and respond to user interactions.

For example, JavaScript can find a button on a page and change its text:

const button = document.querySelector('#save-button');

button.textContent = 'Saved';

This simple example demonstrates one of the most important patterns in browser-based JavaScript:

  1. Find an HTML element.
  2. Store a reference to it.
  3. Use JavaScript to work with that element.

What Is the DOM?

DOM stands for Document Object Model.

When a browser loads an HTML document, it parses the HTML and creates an in-memory object representation of the document. JavaScript can access this representation through the global document object.

Consider this HTML:

<!DOCTYPE html>
<html>
<head>
    <title>My Website</title>
</head>
<body>
    <h1>Welcome</h1>
    <p>Learning JavaScript</p>
</body>
</html>

The browser builds a hierarchical structure from this document.

Conceptually, it looks like:

document
└── html
    ├── head
    │   └── title
    └── body
        ├── h1
        └── p

JavaScript can navigate this structure and interact with individual elements.

The Document Object

The document object represents the webpage currently loaded in the browser.

It provides many properties and methods for working with the DOM.

For example:

console.log(document);

You can also inspect the page title:

console.log(document.title);

And you can access the body:

console.log(document.body);

The document object is one of the most important objects in browser JavaScript.

DOM Nodes

The DOM is made up of different types of nodes.

Common node types include:

  • Document nodes
  • Element nodes
  • Text nodes
  • Comment nodes

HTML elements such as <div>, <p>, <button> and <h1> are represented as element nodes.

Text written inside an element is represented by a text node.

For most everyday web development tasks, you will work primarily with element objects.

Parent and Child Relationships

DOM elements have relationships with other elements.

For example:

<div id="container">
    <h2>Dashboard</h2>
    <p>Welcome student</p>
</div>

The div is the parent of the h2 and p elements.

The h2 and p elements are children of the div.

JavaScript can inspect these relationships using properties such as:

element.parentElement
element.children
element.firstElementChild
element.lastElementChild
element.nextElementSibling
element.previousElementSibling

Selecting Elements

Before JavaScript can manipulate an element, it normally needs to obtain a reference to that element.

There are several ways to select elements from the DOM.

The most commonly used methods include:

  • getElementById()
  • getElementsByClassName()
  • getElementsByTagName()
  • querySelector()
  • querySelectorAll()

getElementById()

The getElementById() method finds an element using its unique id attribute.

HTML:

<h1 id="page-title">Student Dashboard</h1>

JavaScript:

const title = document.getElementById('page-title');

console.log(title);

The returned value is the element itself.

You can then work with it:

const title = document.getElementById('page-title');

title.textContent = 'My Student Dashboard';

IDs should generally be unique within a page. This makes getElementById() useful when you know you are targeting one specific element.

When an ID Does Not Exist

If the requested ID cannot be found, getElementById() returns null.

const element = document.getElementById('does-not-exist');

console.log(element);

The result will be:

null

Trying to use a property or method on null will cause an error.

For this reason, checking the result can be useful:

const button = document.getElementById('save-button');

if (button) {
    button.textContent = 'Save';
}

getElementsByClassName()

The getElementsByClassName() method selects elements that contain a specified class name.

HTML:

<p class="course-title">Web Development</p>
<p class="course-title">Data Analysis</p>
<p class="course-title">Cyber Security</p>

JavaScript:

const titles = document.getElementsByClassName('course-title');

console.log(titles);

This returns a collection containing all matching elements.

You can access an individual item using an index:

console.log(titles[0]);
console.log(titles[1]);
console.log(titles[2]);

The first item is at index 0.

Working With HTMLCollections

getElementsByClassName() returns an HTMLCollection.

An HTMLCollection is an array-like collection, but it is not a normal JavaScript array.

You can loop through it:

const titles = document.getElementsByClassName('course-title');

for (let i = 0; i < titles.length; i++) {
    console.log(titles[i].textContent);
}

It is important to remember that an HTMLCollection does not provide all the methods available on regular arrays.

getElementsByTagName()

The getElementsByTagName() method selects elements based on their HTML tag name.

For example:

const paragraphs = document.getElementsByTagName('p');

console.log(paragraphs);

This selects every <p> element in the document.

You can also select headings:

const headings = document.getElementsByTagName('h2');

Like getElementsByClassName(), this method returns an HTMLCollection.

querySelector()

querySelector() is one of the most flexible DOM selection methods.

It accepts a CSS selector and returns the first matching element.

For example, to select an ID:

const title = document.querySelector('#page-title');

To select a class:

const card = document.querySelector('.course-card');

To select a tag:

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

Because it accepts CSS selectors, it can also select more complex structures.

const button = document.querySelector('.course-card button');

This selects the first button found inside an element with the class course-card.

querySelector() Returns Only the First Match

A common mistake is expecting querySelector() to return every matching element.

Consider:

<button class="course-button">Course 1</button>
<button class="course-button">Course 2</button>
<button class="course-button">Course 3</button>

This:

const button = document.querySelector('.course-button');

returns only the first matching button.

When multiple matching elements are required, use querySelectorAll().

querySelectorAll()

querySelectorAll() returns all elements matching a CSS selector.

Example:

const buttons = document.querySelectorAll('.course-button');

console.log(buttons);

The result is a NodeList.

You can use forEach() with a NodeList:

const buttons = document.querySelectorAll('.course-button');

buttons.forEach(function(button) {
    console.log(button.textContent);
});

An arrow function can make the same code shorter:

buttons.forEach(button => {
    console.log(button.textContent);
});

CSS Selectors With querySelector()

Because querySelector() and querySelectorAll() understand CSS selectors, they are extremely flexible.

ID selector:

document.querySelector('#student-name');

Class selector:

document.querySelector('.student-card');

Tag selector:

document.querySelector('button');

Attribute selector:

document.querySelector('[data-course]');

Descendant selector:

document.querySelector('.dashboard .profile');

Child selector:

document.querySelector('.menu > li');

Multiple selector:

document.querySelector('.primary, .secondary');

Selecting Elements Inside Another Element

DOM selection does not have to start from the entire document.

You can first select a parent element and then search inside it.

HTML:

<div class="course-card">
    <h2>Web Development</h2>
    <button>Explore Course</button>
</div>

JavaScript:

const card = document.querySelector('.course-card');

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

console.log(button);

This approach is useful when pages contain repeated components.

Checking Whether an Element Exists

Before manipulating an element, it is often useful to make sure it was successfully selected.

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

if (message) {
    message.textContent = 'Welcome!';
}

This prevents JavaScript from attempting to manipulate an element that does not exist.

DOM Selection and Script Loading

One common beginner problem happens when JavaScript runs before the HTML element it is trying to select has been created.

For example, if the script executes too early:

const button = document.querySelector('#save-button');

The result may be null because the browser has not yet parsed the button.

One solution is to place the script near the end of the body:

<body>

    <button id="save-button">Save</button>

    <script src="app.js"></script>
</body>

Another solution is to use the defer attribute:

<script src="app.js" defer></script>

The defer attribute allows the browser to continue parsing the HTML while preparing the script, then execute the script after the document has been parsed.

DOMContentLoaded

JavaScript can also wait for the DOM to finish loading by listening for the DOMContentLoaded event.

document.addEventListener('DOMContentLoaded', () => {
    const button = document.querySelector('#save-button');

    if (button) {
        console.log('Button found.');
    }
});

This is useful when your script must wait until the document structure is ready.

Inspecting Element Relationships

Once an element has been selected, JavaScript can inspect its position within the DOM.

For example:

const item = document.querySelector('.course-item');

console.log(item.parentElement);
console.log(item.children);
console.log(item.firstElementChild);
console.log(item.lastElementChild);

You can also inspect neighboring elements:

console.log(item.nextElementSibling);
console.log(item.previousElementSibling);

children

The children property returns the element’s child elements.

Example:

const container = document.querySelector('#container');

console.log(container.children);

You can access a particular child by index:

console.log(container.children[0]);

parentElement

The parentElement property returns the parent element.

const button = document.querySelector('#save-button');

console.log(button.parentElement);

This is useful when you need to move from a selected child element back to its containing component.

firstElementChild and lastElementChild

These properties provide quick access to the first and last child elements.

const list = document.querySelector('#course-list');

console.log(list.firstElementChild);
console.log(list.lastElementChild);

nextElementSibling and previousElementSibling

These properties allow JavaScript to move between neighboring elements.

const current = document.querySelector('.active');

console.log(current.nextElementSibling);
console.log(current.previousElementSibling);

Practical Example: Selecting a Student Name

HTML:

<h2 id="student-name">Student</h2>

JavaScript:

const studentName = document.querySelector('#student-name');

studentName.textContent = 'John';

The browser will display the new name inside the heading.

Practical Example: Selecting Multiple Course Cards

HTML:

<div class="course-card">Web Development</div>
<div class="course-card">Data Analysis</div>
<div class="course-card">Cyber Security</div>

JavaScript:

const courses = document.querySelectorAll('.course-card');

courses.forEach(course => {
    console.log(course.textContent);
});

This gives JavaScript access to every course card.

Practical Example: Finding a Button Inside a Card

HTML:

<article class="course-card">
    <h2>Web Development</h2>
    <p>Learn modern web development.</p>
    <button>Explore Course</button>
</article>

JavaScript:

const card = document.querySelector('.course-card');
const button = card.querySelector('button');

console.log(button.textContent);

This pattern is useful for interactive cards, dashboards, navigation systems and LMS interfaces.

Using data Attributes

HTML allows developers to create custom data attributes beginning with data-.

<button data-course="web-development">
    Explore Course
</button>

You can select the element using:

const button = document.querySelector('[data-course]');

You can also target a specific value:

const button = document.querySelector(
    '[data-course="web-development"]'
);

Data attributes are particularly useful for connecting HTML components to JavaScript behavior.

querySelector vs getElementById

Both methods can select an element by ID.

const title1 = document.getElementById('page-title');

const title2 = document.querySelector('#page-title');

Both can return the same element.

getElementById() is specifically designed for IDs, while querySelector() supports the full CSS selector syntax.

Modern projects commonly use querySelector() and querySelectorAll() because they provide a consistent selector-based approach.

querySelectorAll vs getElementsByClassName

These methods can both be used to retrieve multiple elements, but their return types differ.

getElementsByClassName() returns an HTMLCollection.

querySelectorAll() returns a NodeList.

Example:

const cards = document.getElementsByClassName('course-card');

const cards2 = document.querySelectorAll('.course-card');

Both can be useful, but querySelectorAll() provides CSS selector flexibility.

Static and Live Collections

An important DOM concept is that different collection methods behave differently when the document changes.

querySelectorAll() returns a static NodeList. The collection represents the matching elements at the time the selection is made.

Some methods such as getElementsByClassName() return live HTMLCollections. The collection can automatically reflect later changes to matching elements.

Understanding this difference becomes important when building applications that dynamically add or remove elements.

Common DOM Selection Mistakes

1. Forgetting the # for an ID

Incorrect:

document.querySelector('student-name');

Correct:

document.querySelector('#student-name');

2. Forgetting the Dot for a Class

Incorrect:

document.querySelector('course-card');

Correct:

document.querySelector('.course-card');

3. Assuming querySelector() Returns All Matches

Incorrect assumption:

const buttons = document.querySelector('.button');

If several elements have the class, only the first match is returned.

Use:

const buttons = document.querySelectorAll('.button');

4. Manipulating a Null Result

This can cause an error:

const button = document.querySelector('#missing-button');

button.textContent = 'Save';

Safer:

const button = document.querySelector('#missing-button');

if (button) {
    button.textContent = 'Save';
}

5. Running the Script Too Early

If the script runs before the required HTML has been parsed, element selection may fail.

Use defer, place the script appropriately, or wait for DOMContentLoaded.

DOM Selection Best Practices

  • Use meaningful IDs and class names.
  • Prefer querySelector() for flexible single-element selection.
  • Use querySelectorAll() when multiple matches are required.
  • Check whether an element exists before manipulating it when its presence is uncertain.
  • Keep JavaScript selectors consistent with your HTML structure.
  • Avoid unnecessarily complicated selectors.
  • Use data-* attributes when HTML elements need JavaScript-specific identifiers.
  • Use defer for external scripts when appropriate.
  • Scope searches to a parent component when working with repeated UI components.

DOM Selection in an LMS

DOM selection is especially useful when developing an LMS such as a student dashboard.

For example, a dashboard might contain:

<section class="dashboard">

    <h1 id="student-name">Student Dashboard</h1>

    <div class="course-card">
        <h2>Web Development</h2>
        <button class="continue-course">
            Continue
        </button>
    </div>

    <div class="course-card">
        <h2>Data Analysis</h2>
        <button class="continue-course">
            Continue
        </button>
    </div>

</section>

JavaScript can select the dashboard:

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

Select the student name:

const studentName = document.querySelector('#student-name');

Select all course cards:

const courseCards = document.querySelectorAll('.course-card');

Select all Continue buttons:

const continueButtons = document.querySelectorAll('.continue-course');

This creates the foundation for making the dashboard interactive.

Mini Practical Project

Create a small student course panel.

HTML:

<div id="course-panel">

    <h2 id="course-title">Course Title</h2>

    <p class="course-description">
        Course description goes here.
    </p>

    <button class="start-course">
        Start Course
    </button>

</div>

JavaScript:

const panel = document.querySelector('#course-panel');

const title = panel.querySelector('#course-title');

const description = panel.querySelector(
    '.course-description'
);

const button = panel.querySelector('.start-course');

console.log(panel);
console.log(title);
console.log(description);
console.log(button);

Now modify the title:

title.textContent = 'JavaScript Fundamentals';

Modify the description:

description.textContent =
    'Learn how JavaScript works with web pages.';

Modify the button text:

button.textContent = 'Continue Learning';

This demonstrates the basic DOM workflow:

HTML
 ↓
DOM
 ↓
JavaScript selects elements
 ↓
JavaScript reads or changes elements

Understanding the DOM Tree

Thinking of the DOM as a tree makes it easier to understand how JavaScript navigates webpages.

For example:

document
└── body
    └── main
        └── section
            ├── h1
            ├── p
            └── button

JavaScript can select an element from anywhere in the tree and then move to related elements.

This concept becomes even more important when you start learning DOM manipulation and event handling.

Summary

The Document Object Model is the browser’s object representation of an HTML document. JavaScript uses the DOM to interact with webpages.

The document object provides methods for finding and working with elements.

The most important selection methods introduced in this lesson are:

  • getElementById() — selects an element by ID.
  • getElementsByClassName() — selects elements by class.
  • getElementsByTagName() — selects elements by tag name.
  • querySelector() — selects the first element matching a CSS selector.
  • querySelectorAll() — selects all elements matching a CSS selector.

You also learned about parent and child relationships, HTMLCollections, NodeLists, DOM loading and practical element selection.

These concepts form the foundation for the next stage of JavaScript development: changing DOM content, attributes and styles dynamically.

💻

Code Example

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>DOM Selection Practice</title>
</head>
<body>

    <section class="dashboard">

        <h1 id="student-name">Student Dashboard</h1>

        <div class="course-card">
            <h2>Web Development</h2>
            <p>Learn HTML, CSS and JavaScript.</p>
            <button class="continue-course">Continue</button>
        </div>

        <div class="course-card">
            <h2>Data Analysis</h2>
            <p>Learn how to work with data.</p>
            <button class="continue-course">Continue</button>
        </div>

    </section>

    <script>
        const studentName = document.querySelector('#student-name');

        const courseCards = document.querySelectorAll('.course-card');

        const continueButtons = document.querySelectorAll(
            '.continue-course'
        );

        studentName.textContent = 'Welcome, Student';

        courseCards.forEach(card => {
            console.log(card.textContent);
        });

        continueButtons.forEach(button => {
            console.log(button.textContent);
        });
    </script>

</body>
</html>
⭐

Key Takeaways

["The DOM is the browser object representation of an HTML document.","JavaScript uses the document object to interact with webpage elements.","getElementById() selects one element by its unique ID.","getElementsByClassName() returns an HTMLCollection of matching elements.","getElementsByTagName() returns an HTMLCollection of matching tags.","querySelector() returns the first element matching a CSS selector.","querySelectorAll() returns all matching elements as a NodeList.","DOM elements have parent, child and sibling relationships.","Always consider whether a selected element exists before manipulating it.","The DOM selection techniques learned here are the foundation for dynamic JavaScript interfaces."]

Enjoying this lesson?

Sign in to your Dwallnet Academy student account to track your learning progress and mark lessons as complete.

Sign In to Track Progress