Manipulating DOM Elements — Complete Guide
In this tutorial, you will learn about Manipulating DOM Elements. We cover key concepts, practical examples, and best practices to help you master this topic.
DOM element manipulation involves changing content, attributes, and structure using properties like textContent, innerHTML, setAttribute, and appendChild to create dynamic user interfaces.
What You'll Learn
- How to change element content with textContent and innerHTML
- How to add, remove, and toggle attributes
- How to insert, move, and remove elements from the DOM tree
- The difference between appendChild, insertBefore, and replaceChild
Why It Matters
Static HTML pages cannot respond to user actions. DOM manipulation is what makes pages interactive — updating text, showing notifications, toggling visibility, and rearranging content based on user input.
Real-World Use
- A chat application appends new messages to the conversation container
- An online code editor updates the preview pane as the user types
- A dashboard replaces chart data and updates display elements without page reload
flowchart LR A[Select Element] --> B[Change Content] A --> C[Change Attributes] A --> D[Change Structure] B --> E[textContent / innerHTML] C --> F[setAttribute / removeAttribute] D --> G[appendChild / insertBefore] D --> H[removeChild / replaceChild] D --> I[prepend / append / after / before]
Changing Element Content
The two main ways to change content are textContent (safe, text-only) and innerHTML (parses HTML, security risk).
const output = document.getElementById('output');
// textContent: safe, no HTML parsing
output.textContent = 'Hello, World!';
console.log(output.textContent);
// innerHTML: parses HTML tags
output.innerHTML = '<strong>Hello</strong>, World!';
console.log(output.innerHTML);
console.log(output.textContent);
// Security warning: never use innerHTML with user input
const userInput = '<img src=x onerror=alert(1)>';
// output.innerHTML = userInput; // XSS vulnerability!
// Always sanitize or use textContent for user data
Expected output: The first assignment shows plain text. The second shows bold "Hello" rendered. The textContent returns "Hello, World!" without tags. The innerHTML returns the HTML string with tags.
Changing Attributes
Use setAttribute, getAttribute, removeAttribute, and the direct property API for common attributes.
const img = document.querySelector('img');
// Set attributes
img.setAttribute('alt', 'A beautiful landscape');
img.setAttribute('loading', 'lazy');
// Get attribute
console.log('Alt text:', img.getAttribute('alt'));
// Direct property access (for standard properties)
img.src = 'new-image.jpg';
img.alt = 'Updated description';
img.width = 800;
// Remove attribute
img.removeAttribute('title');
// Check if attribute exists
console.log('Has alt:', img.hasAttribute('alt'));
console.log('Has title:', img.hasAttribute('title'));
Expected output: The alt text, confirmation of alt attribute presence, and confirmation that title attribute is absent.
Adding and Removing Elements
The DOM API provides several methods for structural changes.
const list = document.querySelector('ul');
// Create and append
const newItem = document.createElement('li');
newItem.textContent = 'Item 4';
list.appendChild(newItem);
// Insert at a specific position
const firstItem = document.createElement('li');
firstItem.textContent = 'Item 0';
list.insertBefore(firstItem, list.firstChild);
// Modern insertion methods
const lastItem = document.createElement('li');
lastItem.textContent = 'Item 5';
list.append(lastItem); // at end
const secondItem = document.createElement('li');
secondItem.textContent = 'Item 1.5';
list.children[1].after(secondItem); // after second child
// Remove an element
const toRemove = document.querySelector('.old-item');
if (toRemove) {
toRemove.remove(); // modern API
}
// Older way
// toRemove.parentNode.removeChild(toRemove);
Expected output: The list dynamically updates with new items inserted at the correct positions and the old item removed.
Moving Elements
Moving an element is done by appending it to a new parent. An element can exist in only one place in the DOM tree.
const sourceList = document.getElementById('source');
const targetList = document.getElementById('target');
// Move the last item from source to target
const itemToMove = sourceList.lastElementChild;
if (itemToMove) {
targetList.appendChild(itemToMove);
console.log('Moved:', itemToMove.textContent);
}
// Verify counts
console.log('Source items:', sourceList.children.length);
console.log('Target items:', targetList.children.length);
// The element is not cloned — it is physically moved.
// appendChild automatically removes it from the old parent.
Expected output: The element disappears from the source list and appears in the target list. The counts reflect the change.
Cloning Elements
Use cloneNode to duplicate an element. The boolean parameter controls deep cloning.
const original = document.querySelector('.card');
// Shallow clone: only the element itself
const shallowClone = original.cloneNode(false);
console.log('Shallow children:', shallowClone.children.length);
// Deep clone: element and all descendants
const deepClone = original.cloneNode(true);
console.log('Deep children:', deepClone.children.length);
// Modify the clone
deepClone.querySelector('h3').textContent = 'Cloned Card';
document.body.appendChild(deepClone);
// Note: cloneNode does not copy event listeners
// or data associated via JavaScript properties
Expected output: The shallow clone has zero children. The deep clone has the same child structure as the original. The new card appears at the bottom of the page.
Common Mistakes
- Using innerHTML with user input — This creates XSS vulnerabilities. Always use textContent for text and sanitize any HTML before using innerHTML.
- Forgetting to re-query after DOM changes — Stored element references become stale or detached if the element is removed. Re-query the DOM if you need fresh references.
- Confusing appendChild with append —
appendChildreturns the appended node and accepts only one node argument.appendaccepts multiple nodes and strings but returns undefined. - Removing an element without checking existence — Calling
remove()on null throws a TypeError. Always check that the element exists before removing. - Expecting cloneNode to copy event listeners —
cloneNodeonly copies HTML attributes and structure. Event listeners added via addEventListener are not cloned.
Practice Questions
- What is the difference between textContent and innerHTML? textContent sets plain text (safe, no Parsing). innerHTML parses the string as HTML (faster for markup, but XSS risk).
- How do you insert an element before another element? Use
parent.insertBefore(newElement, referenceElement)orreferenceElement.before(newElement). - Can an element exist in two places in the DOM at once? No. An element can only have one parent. Appending a moved element removes it from its previous location.
- Challenge: Write a function that swaps two DOM elements by position. Handle edge cases where elements are siblings vs in different parts of the tree.
FAQ
Mini Project
Create a task list application with an input field and add button. When the user types a task and clicks Add, create a new list item with the task text and a delete button. Clicking the delete button removes that specific item. Use textContent for safety, appendChild for insertion, and remove for deletion.
What's Next
Continue with Lesson 6: Classes and Attributes to learn how to manage CSS classes and data attributes on DOM elements.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro