Manipulating the DOM
Learning Objectives
- By the end of this lesson, you will be able to:
- - Create new DOM elements
- - Add elements to the DOM
- - Remove elements from the DOM
- - Modify element content (text and HTML)
- - Change element attributes
- - Add and remove CSS classes
- - Update element styles
- - Build dynamic web pages
Lesson 13.2: Manipulating the DOM
Learning Objectives
By the end of this lesson, you will be able to:
- Create new DOM elements
- Add elements to the DOM
- Remove elements from the DOM
- Modify element content (text and HTML)
- Change element attributes
- Add and remove CSS classes
- Update element styles
- Build dynamic web pages
Introduction to DOM Manipulation
DOM manipulation allows you to dynamically change the content, structure, and appearance of web pages using JavaScript.
Why Manipulate the DOM?
- Dynamic Content: Update page without reload
- User Interaction: Respond to user actions
- Real-time Updates: Show live data
- Interactive UIs: Build modern web applications
Creating Elements
createElement()
Create a new HTML element:
// Create a div element
let div = document.createElement('div');
// Create a paragraph
let paragraph = document.createElement('p');
// Create a button
let button = document.createElement('button');
Setting Element Properties
let div = document.createElement('div');
div.id = 'myDiv';
div.className = 'container';
div.textContent = 'Hello World';
Creating Elements with Attributes
let link = document.createElement('a');
link.href = 'https://example.com';
link.textContent = 'Visit Example';
link.target = '_blank';
Adding Elements to DOM
appendChild()
Add element as the last child:
let container = document.getElementById('container');
let newDiv = document.createElement('div');
newDiv.textContent = 'New content';
container.appendChild(newDiv);
insertBefore()
Insert element before another element:
let container = document.getElementById('container');
let newDiv = document.createElement('div');
let existingDiv = document.getElementById('existing');
container.insertBefore(newDiv, existingDiv);
insertAdjacentElement()
Insert element at specific position:
let element = document.getElementById('target');
// beforebegin: Before element
element.insertAdjacentElement('beforebegin', newElement);
// afterbegin: First child
element.insertAdjacentElement('afterbegin', newElement);
// beforeend: Last child
element.insertAdjacentElement('beforeend', newElement);
// afterend: After element
element.insertAdjacentElement('afterend', newElement);
prepend() and append()
Modern methods (may need polyfill for older browsers):
let container = document.getElementById('container');
// Add at beginning
container.prepend(newElement);
// Add at end
container.append(newElement);
Removing Elements
removeChild()
Remove a child element:
let container = document.getElementById('container');
let child = document.getElementById('child');
container.removeChild(child);
remove()
Modern method to remove element:
let element = document.getElementById('myElement');
element.remove();
Clearing All Children
let container = document.getElementById('container');
// Method 1: Remove all children
while (container.firstChild) {
container.removeChild(container.firstChild);
}
// Method 2: Clear innerHTML
container.innerHTML = '';
// Method 3: Modern way
container.replaceChildren();
Modifying Element Content
textContent
Get or set text content (strips HTML):
let element = document.getElementById('myDiv');
// Get text content
console.log(element.textContent); // "Hello World"
// Set text content
element.textContent = 'New text';
innerHTML
Get or set HTML content:
let element = document.getElementById('myDiv');
// Get HTML
console.log(element.innerHTML); // "<span>Hello</span>"
// Set HTML
element.innerHTML = '<strong>Bold text</strong>';
innerText
Get or set visible text (respects CSS):
let element = document.getElementById('myDiv');
element.innerText = 'Visible text';
Comparison
| Property | Gets | Sets | HTML Support |
|---|---|---|---|
textContent |
All text | Plain text | No |
innerHTML |
HTML string | HTML string | Yes |
innerText |
Visible text | Plain text | No |
Changing Attributes
getAttribute() and setAttribute()
let element = document.getElementById('myLink');
// Get attribute
let href = element.getAttribute('href');
// Set attribute
element.setAttribute('href', 'https://example.com');
element.setAttribute('target', '_blank');
element.setAttribute('data-id', '123');
Direct Property Access
let element = document.getElementById('myLink');
// Set properties directly
element.href = 'https://example.com';
element.id = 'newId';
element.className = 'newClass';
hasAttribute() and removeAttribute()
let element = document.getElementById('myDiv');
// Check if attribute exists
if (element.hasAttribute('data-id')) {
console.log('Has data-id');
}
// Remove attribute
element.removeAttribute('data-id');
data-* Attributes
let element = document.getElementById('myDiv');
// Set data attribute
element.setAttribute('data-user-id', '123');
element.setAttribute('data-status', 'active');
// Access via dataset
console.log(element.dataset.userId); // "123"
console.log(element.dataset.status); // "active"
// Set via dataset
element.dataset.userId = '456';
element.dataset.newAttribute = 'value';
Working with Classes
className
Get or set all classes:
let element = document.getElementById('myDiv');
// Get classes
console.log(element.className); // "class1 class2"
// Set classes
element.className = 'newClass';
element.className = 'class1 class2 class3';
classList
Modern API for class manipulation:
let element = document.getElementById('myDiv');
// Add class
element.classList.add('newClass');
element.classList.add('class1', 'class2');
// Remove class
element.classList.remove('oldClass');
element.classList.remove('class1', 'class2');
// Toggle class
element.classList.toggle('active');
// Check if has class
if (element.classList.contains('active')) {
console.log('Has active class');
}
// Replace class
element.classList.replace('oldClass', 'newClass');
classList Methods
let element = document.getElementById('myDiv');
// Add multiple classes
element.classList.add('class1', 'class2', 'class3');
// Remove multiple classes
element.classList.remove('class1', 'class2');
// Toggle with condition
element.classList.toggle('active', true); // Force add
element.classList.toggle('active', false); // Force remove
// Get all classes as array
let classes = Array.from(element.classList);
console.log(classes); // ["class1", "class2"]
Changing Styles
style Property
Set inline styles:
let element = document.getElementById('myDiv');
// Set individual styles
element.style.color = 'red';
element.style.backgroundColor = 'blue';
element.style.fontSize = '20px';
element.style.display = 'none';
style Property (camelCase)
CSS properties use camelCase in JavaScript:
element.style.backgroundColor = 'red'; // background-color
element.style.fontSize = '16px'; // font-size
element.style.marginTop = '10px'; // margin-top
element.style.zIndex = '100'; // z-index
getComputedStyle()
Get computed styles (including CSS):
let element = document.getElementById('myDiv');
let styles = window.getComputedStyle(element);
console.log(styles.color);
console.log(styles.backgroundColor);
console.log(styles.fontSize);
Setting Multiple Styles
// Method 1: Individual properties
element.style.color = 'red';
element.style.fontSize = '20px';
// Method 2: cssText
element.style.cssText = 'color: red; font-size: 20px; background: blue;';
// Method 3: Object.assign
Object.assign(element.style, {
color: 'red',
fontSize: '20px',
backgroundColor: 'blue'
});
Practical Examples
Example 1: Creating a List
function createList(items) {
let ul = document.createElement('ul');
items.forEach(item => {
let li = document.createElement('li');
li.textContent = item;
ul.appendChild(li);
});
return ul;
}
let list = createList(['Apple', 'Banana', 'Orange']);
document.body.appendChild(list);
Example 2: Dynamic Card Creation
function createCard(title, content) {
let card = document.createElement('div');
card.className = 'card';
let cardTitle = document.createElement('h2');
cardTitle.textContent = title;
cardTitle.className = 'card-title';
let cardContent = document.createElement('p');
cardContent.textContent = content;
cardContent.className = 'card-content';
card.appendChild(cardTitle);
card.appendChild(cardContent);
return card;
}
let card = createCard('My Title', 'Card content here');
document.getElementById('container').appendChild(card);
Example 3: Toggle Visibility
function toggleElement(elementId) {
let element = document.getElementById(elementId);
if (element.style.display === 'none') {
element.style.display = 'block';
} else {
element.style.display = 'none';
}
}
// Or using classList
function toggleElement(elementId) {
let element = document.getElementById(elementId);
element.classList.toggle('hidden');
}
Example 4: Form Validation Display
function showError(inputId, message) {
let input = document.getElementById(inputId);
// Remove existing error
let existingError = input.parentElement.querySelector('.error');
if (existingError) {
existingError.remove();
}
// Add error class
input.classList.add('error');
// Create error message
let errorDiv = document.createElement('div');
errorDiv.className = 'error';
errorDiv.textContent = message;
errorDiv.style.color = 'red';
input.parentElement.appendChild(errorDiv);
}
Practice Exercise
Exercise: DOM Manipulation
Objective: Practice creating, modifying, and removing DOM elements.
Instructions:
- Create an HTML file with a container
- Create a JavaScript file for manipulation
- Practice:
- Creating elements
- Adding elements
- Removing elements
- Modifying content
- Changing attributes and classes
- Updating styles
Example Solution:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>DOM Manipulation Practice</title>
<style>
.card {
border: 1px solid #ccc;
padding: 20px;
margin: 10px;
border-radius: 5px;
}
.highlight {
background-color: yellow;
}
.hidden {
display: none;
}
</style>
</head>
<body>
<div id="container">
<h1>DOM Manipulation Practice</h1>
<button id="addBtn">Add Card</button>
<button id="removeBtn">Remove Last</button>
<button id="toggleBtn">Toggle Highlight</button>
</div>
<script src="dom-manipulation.js"></script>
</body>
</html>
// dom-manipulation.js
console.log("=== DOM Manipulation Practice ===");
console.log("\n=== Creating Elements ===");
// Create a div
let div = document.createElement('div');
div.id = 'myDiv';
div.className = 'card';
div.textContent = 'Created with createElement';
console.log("Created div:", div);
// Create a paragraph
let paragraph = document.createElement('p');
paragraph.textContent = 'This is a paragraph';
paragraph.style.color = 'blue';
console.log("Created paragraph:", paragraph);
// Create a button
let button = document.createElement('button');
button.textContent = 'Click Me';
button.className = 'btn';
button.setAttribute('data-action', 'click');
console.log("Created button:", button);
console.log();
console.log("=== Adding Elements ===");
let container = document.getElementById('container');
// Append child
let newDiv = document.createElement('div');
newDiv.textContent = 'Appended element';
newDiv.className = 'card';
container.appendChild(newDiv);
console.log("Appended element to container");
// Insert before
let beforeDiv = document.createElement('div');
beforeDiv.textContent = 'Inserted before';
beforeDiv.className = 'card';
container.insertBefore(beforeDiv, newDiv);
console.log("Inserted element before");
// Using insertAdjacentElement
let adjacentDiv = document.createElement('div');
adjacentDiv.textContent = 'Adjacent element';
adjacentDiv.className = 'card';
container.insertAdjacentElement('beforeend', adjacentDiv);
console.log("Inserted adjacent element");
console.log();
console.log("=== Modifying Content ===");
let contentDiv = document.createElement('div');
contentDiv.id = 'contentDiv';
// textContent
contentDiv.textContent = 'Plain text content';
console.log("textContent:", contentDiv.textContent);
// innerHTML
contentDiv.innerHTML = '<strong>Bold</strong> and <em>italic</em> text';
console.log("innerHTML:", contentDiv.innerHTML);
console.log("textContent after innerHTML:", contentDiv.textContent);
container.appendChild(contentDiv);
console.log();
console.log("=== Changing Attributes ===");
let link = document.createElement('a');
link.href = 'https://example.com';
link.textContent = 'Visit Example';
link.target = '_blank';
link.setAttribute('data-link-id', '123');
console.log("Link href:", link.getAttribute('href'));
console.log("Link target:", link.target);
console.log("Link data-id:", link.dataset.linkId);
// Update attributes
link.setAttribute('href', 'https://google.com');
link.setAttribute('data-link-id', '456');
console.log("Updated href:", link.getAttribute('href'));
console.log("Updated data-id:", link.dataset.linkId);
console.log();
console.log("=== Working with Classes ===");
let classDiv = document.createElement('div');
classDiv.className = 'card';
// Add classes
classDiv.classList.add('highlight');
classDiv.classList.add('active', 'visible');
console.log("Classes after add:", classDiv.className);
// Remove classes
classDiv.classList.remove('active');
console.log("Classes after remove:", classDiv.className);
// Toggle class
classDiv.classList.toggle('highlight');
console.log("Has highlight:", classDiv.classList.contains('highlight'));
classDiv.classList.toggle('highlight');
console.log("Has highlight after toggle:", classDiv.classList.contains('highlight'));
// Replace class
classDiv.classList.replace('visible', 'hidden');
console.log("Classes after replace:", classDiv.className);
console.log();
console.log("=== Changing Styles ===");
let styleDiv = document.createElement('div');
styleDiv.textContent = 'Styled div';
styleDiv.style.color = 'red';
styleDiv.style.backgroundColor = 'yellow';
styleDiv.style.padding = '20px';
styleDiv.style.border = '2px solid black';
console.log("Color:", styleDiv.style.color);
console.log("Background:", styleDiv.style.backgroundColor);
// Using cssText
let styleDiv2 = document.createElement('div');
styleDiv2.textContent = 'Styled with cssText';
styleDiv2.style.cssText = 'color: blue; font-size: 20px; margin: 10px;';
// Using Object.assign
let styleDiv3 = document.createElement('div');
styleDiv3.textContent = 'Styled with Object.assign';
Object.assign(styleDiv3.style, {
color: 'green',
fontSize: '18px',
padding: '15px'
});
container.appendChild(styleDiv);
container.appendChild(styleDiv2);
container.appendChild(styleDiv3);
console.log();
console.log("=== Removing Elements ===");
// Create elements to remove
let removeDiv1 = document.createElement('div');
removeDiv1.textContent = 'Will be removed';
removeDiv1.id = 'removeMe';
container.appendChild(removeDiv1);
let removeDiv2 = document.createElement('div');
removeDiv2.textContent = 'Will also be removed';
container.appendChild(removeDiv2);
console.log("Container children before removal:", container.children.length);
// Remove by reference
container.removeChild(removeDiv1);
console.log("Removed first element");
// Remove using remove()
removeDiv2.remove();
console.log("Removed second element");
console.log("Container children after removal:", container.children.length);
console.log();
console.log("=== Practical Example: Card Creator ===");
function createCard(title, content, color = 'white') {
let card = document.createElement('div');
card.className = 'card';
card.style.backgroundColor = color;
let cardTitle = document.createElement('h2');
cardTitle.textContent = title;
cardTitle.style.marginTop = '0';
let cardContent = document.createElement('p');
cardContent.textContent = content;
let removeBtn = document.createElement('button');
removeBtn.textContent = 'Remove';
removeBtn.onclick = () => card.remove();
card.appendChild(cardTitle);
card.appendChild(cardContent);
card.appendChild(removeBtn);
return card;
}
// Add cards
let card1 = createCard('Card 1', 'This is the first card', '#f0f0f0');
let card2 = createCard('Card 2', 'This is the second card', '#e0e0e0');
let card3 = createCard('Card 3', 'This is the third card', '#d0d0d0');
container.appendChild(card1);
container.appendChild(card2);
container.appendChild(card3);
console.log("Created 3 cards");
console.log();
console.log("=== Toggle Functionality ===");
let toggleDiv = document.createElement('div');
toggleDiv.id = 'toggleDiv';
toggleDiv.textContent = 'This div can be toggled';
toggleDiv.style.padding = '10px';
toggleDiv.style.border = '1px solid black';
container.appendChild(toggleDiv);
function toggleVisibility(elementId) {
let element = document.getElementById(elementId);
element.classList.toggle('hidden');
console.log("Toggled visibility, is hidden:", element.classList.contains('hidden'));
}
// Test toggle
toggleVisibility('toggleDiv');
toggleVisibility('toggleDiv');
console.log();
console.log("=== List Creator ===");
function createList(items) {
let ul = document.createElement('ul');
ul.style.listStyle = 'none';
ul.style.padding = '0';
items.forEach((item, index) => {
let li = document.createElement('li');
li.textContent = item;
li.style.padding = '5px';
li.style.backgroundColor = index % 2 === 0 ? '#f0f0f0' : '#ffffff';
ul.appendChild(li);
});
return ul;
}
let list = createList(['Apple', 'Banana', 'Orange', 'Grape', 'Mango']);
container.appendChild(list);
console.log("Created list with", list.children.length, "items");
Expected Output (in browser console):
=== DOM Manipulation Practice ===
=== Creating Elements ===
Created div: [div element]
Created paragraph: [p element]
Created button: [button element]
=== Adding Elements ===
Appended element to container
Inserted element before
Inserted adjacent element
=== Modifying Content ===
textContent: Plain text content
innerHTML: <strong>Bold</strong> and <em>italic</em> text
textContent after innerHTML: Bold and italic text
=== Changing Attributes ===
Link href: https://example.com
Link target: _blank
Link data-id: 123
Updated href: https://google.com
Updated data-id: 456
=== Working with Classes ===
Classes after add: card highlight active visible
Classes after remove: card highlight visible
Has highlight: false
Has highlight after toggle: true
Classes after replace: card highlight hidden
=== Changing Styles ===
Color: red
Background: yellow
=== Removing Elements ===
Container children before removal: [number]
Removed first element
Removed second element
Container children after removal: [number]
=== Practical Example: Card Creator ===
Created 3 cards
=== Toggle Functionality ===
Toggled visibility, is hidden: true
Toggled visibility, is hidden: false
=== List Creator ===
Created list with 5 items
Challenge (Optional):
- Build a dynamic form generator
- Create a todo list application
- Build a card-based UI system
- Create a dynamic table generator
Common Mistakes
1. Using innerHTML with User Input
// ⚠️ Security risk: XSS vulnerability
let userInput = "<img src=x onerror='alert(1)'>";
element.innerHTML = userInput; // Dangerous!
// ✅ Solution: Use textContent or sanitize
element.textContent = userInput;
// or use a sanitization library
2. Not Checking Element Existence
// ⚠️ Problem: Element might not exist
let element = document.getElementById('myDiv');
element.appendChild(newElement); // Error if element is null
// ✅ Solution: Always check
let element = document.getElementById('myDiv');
if (element) {
element.appendChild(newElement);
}
3. Creating Elements in Loop Without Optimization
// ⚠️ Problem: Multiple DOM updates
for (let i = 0; i < 1000; i++) {
let div = document.createElement('div');
container.appendChild(div); // Updates DOM each time
}
// ✅ Solution: Use DocumentFragment
let fragment = document.createDocumentFragment();
for (let i = 0; i < 1000; i++) {
let div = document.createElement('div');
fragment.appendChild(div);
}
container.appendChild(fragment); // Single DOM update
4. Confusing textContent and innerHTML
// ⚠️ Problem: innerHTML doesn't work as expected
element.innerHTML = '<strong>Bold</strong>'; // Renders HTML
element.textContent = '<strong>Bold</strong>'; // Shows as text
// ✅ Solution: Use appropriate property
// Use innerHTML for HTML, textContent for plain text
Key Takeaways
- createElement(): Create new elements
- appendChild(): Add elements to DOM
- remove(): Remove elements
- textContent: Plain text content
- innerHTML: HTML content
- setAttribute(): Set attributes
- classList: Modern class manipulation
- style: Inline styles
- Best Practice: Check for null, use DocumentFragment for multiple elements
- Security: Be careful with innerHTML and user input
Quiz: DOM Manipulation
Test your understanding with these questions:
-
createElement() creates:
- A) Element in DOM
- B) Element object (not in DOM)
- C) Text node
- D) Attribute
-
appendChild() adds element:
- A) At beginning
- B) At end
- C) Before element
- D) After element
-
textContent:
- A) Includes HTML
- B) Strips HTML
- C) Renders HTML
- D) Nothing
-
innerHTML:
- A) Plain text only
- B) Renders HTML
- C) Strips HTML
- D) Nothing
-
classList.add() is:
- A) Old method
- B) Modern method
- C) Deprecated
- D) Not available
-
element.remove() is:
- A) Old method
- B) Modern method
- C) Not available
- D) Error
-
DocumentFragment is used for:
- A) Single element
- B) Multiple elements (optimization)
- C) Text nodes
- D) Attributes
Answers:
- B) Element object (not in DOM yet)
- B) At end
- B) Strips HTML
- B) Renders HTML
- B) Modern method
- B) Modern method
- B) Multiple elements (optimization)
Next Steps
Congratulations! You've learned DOM manipulation. You now know:
- How to create elements
- How to add and remove elements
- How to modify content
- How to change attributes and classes
What's Next?
- Lesson 13.3: DOM Traversal
- Learn to navigate the DOM tree
- Understand parent/child relationships
- Build more complex DOM operations
Additional Resources
- MDN: Element: developer.mozilla.org/en-US/docs/Web/API/Element
- MDN: Document.createElement(): developer.mozilla.org/en-US/docs/Web/API/Document/createElement
- JavaScript.info: DOM Manipulation: javascript.info/modifying-document
Lesson completed! You're ready to move on to the next lesson.
Course Navigation
- DOM Basics
- Manipulating the DOM
- DOM Traversal