What is the DOM β Document Object Model
After completing this topic, you will be able to:
- Explain what the DOM is.
- Perform basic operations such as selecting HTML elements, changing their content, and attaching events using JavaScript.
HTML is text, the DOM is an object
When a browser receives an HTML file, it doesn't simply render the text directly onto the screen. Instead, it parses the HTML text and creates a tree-like structure of objects in memory. This object tree is the DOM (Document Object Model).
<html>
<body>
<h1>Hello</h1>
<p>Nice to meet you</p>
</body>
</html>document
βββ html
βββ body
βββ h1 β "Hello"
βββ p β "Nice to meet you"Every HTML tag, text, and attribute becomes a node in this tree. JavaScript can use this tree to read, modify, and delete HTML elements.
Selecting elements
To manipulate the DOM, you must first select the elements you want to work with.
// Select by ID (returns only one element)
const title = document.getElementById('main-title');
// Select by CSS selector (returns the first element that matches)
const firstCard = document.querySelector('.card');
// Select by CSS selector (returns all elements that match)
const allCards = document.querySelectorAll('.card');querySelector is the most versatile because it allows you to use CSS selectors directly. Select classes with .card, IDs with #main-title, and tags with p.
// Combinations are also possible
const activeItem = document.querySelector('ul.menu > li.active');Reading and modifying content
const heading = document.querySelector('h1');
// Read
console.log(heading.textContent); // "Hello"
console.log(heading.innerHTML); // "Hello" (includes HTML tags)
// Modify
heading.textContent = 'Welcome'; // Changes only the text
heading.innerHTML = '<em>Welcome</em>'; // Allows inserting HTMLtextContent deals with plain text, while innerHTML deals with HTML markup. Using innerHTML with user input can lead to XSS attacks, so use textContent for user data.
Changing styles and attributes
const box = document.querySelector('.box');
// Change inline styles
box.style.backgroundColor = '#3498db';
box.style.padding = '20px';
// Manipulate CSS classes (recommended)
box.classList.add('active');
box.classList.remove('hidden');
box.classList.toggle('selected');You can also change inline styles directly, but it's better for maintainability to add or remove CSS classes. This separates styles in CSS files and behavior in JavaScript.
// Change attributes
const img = document.querySelector('img');
img.setAttribute('src', 'new-image.png');
img.setAttribute('alt', 'New image');
// Data attributes
const card = document.querySelector('[data-id="42"]');
console.log(card.dataset.id); // "42"Creating and adding elements
// Create a new element
const newItem = document.createElement('li');
newItem.textContent = 'New item';
newItem.classList.add('item');
// Add to an existing element
const list = document.querySelector('ul');
list.appendChild(newItem); // Add to the end
list.prepend(newItem); // Add to the beginning
list.insertBefore(newItem, list.children[1]); // Insert at a specific location// When adding multiple elements at once
const fragment = document.createDocumentFragment();
for (let i = 0; i < 100; i++) {
const li = document.createElement('li');
li.textContent = `Item ${i}`;
fragment.appendChild(li);
}
list.appendChild(fragment); // Only one DOM accessUsing DocumentFragment allows you to group repetitive DOM modifications and process them at once. Accessing the DOM is an expensive operation, so reducing the number of times you access it improves performance.
Events β Responding to user actions
const button = document.querySelector('#submit');
button.addEventListener('click', function(event) {
console.log('Button clicked');
console.log(event.target); // The element that was clicked
});addEventListener has three parts:
- Event name:
'click','input','submit','keydown', etc. - Callback function: The function to execute when the event occurs.
eventobject: Contains information about the event (which key was pressed, mouse coordinates, etc.).
// React to input field changes in real-time
const input = document.querySelector('#search');
input.addEventListener('input', function(e) {
console.log('Current input:', e.target.value);
});Event delegation
Instead of attaching an event to each of 100 buttons, you can attach one to the parent:
// β Inefficient β 100 listeners
document.querySelectorAll('.item').forEach(item => {
item.addEventListener('click', handleClick);
});
// β
Event delegation β 1 listener
document.querySelector('#list').addEventListener('click', function(e) {
if (e.target.classList.contains('item')) {
console.log('Clicked item:', e.target.textContent);
}
});Click events bubble from the child to the parent. You can identify the actual clicked child by checking e.target in the parent. This also has the advantage of automatically applying to dynamically added elements.
textContent vs. innerHTML security
const userInput = '<script>alert("Hacked")</script>';
element.innerHTML = userInput; // β Dangerous β potential XSS attack
element.textContent = userInput; // β
Safe β tags are displayed as textPutting user input into innerHTML can execute malicious scripts. Always use textContent for user input. If you need to dynamically create HTML structures, it's safer to assemble them using createElement.
DOM and frameworks
When using modern front-end frameworks (React, Vue, Svelte), you don't manipulate the DOM directly. The framework handles this for you using a Virtual DOM or a compiler:
Direct DOM manipulation:
Developer β querySelector β Direct DOM modification
React approach:
Developer β state change β React modifies the DOMHowever, if you don't understand the DOM's principles:
- You won't understand how the framework works.
- You won't be able to debug performance issues.
- You won't be able to create quick prototypes without a framework.
Key Summary
| Operation | Method |
|---|---|
| Select | querySelector(), querySelectorAll() |
| Read/Modify | textContent, innerHTML |
| Style | classList.add/remove/toggle |
| Create | createElement(), appendChild() |
| Event | addEventListener() |
| Event delegation | Listener on parent + e.target check |
The DOM is the core interface that JavaScript uses to dynamically create web pages. Even when using frameworks like React, understanding how the DOM works can greatly help with debugging and optimization.