Skip to content

Creating and Removing DOM Nodes — Complete Guide

DodaTech Updated 2026-06-28 7 min read

In this tutorial, you will learn about Creating and Removing DOM Nodes. We cover key concepts, practical examples, and best practices to help you master this topic.

Creating and removing DOM nodes using createElement, appendChild, removeChild, and remove enables dynamic page updates without reloading the entire document from the server.

What You'll Learn

  • How to create element nodes, text nodes, and comment nodes
  • How to insert new nodes at various positions in the tree
  • How to safely remove nodes and clean up resources
  • Patterns for efficient bulk creation and insertion

Why It Matters

Modern web applications create and destroy DOM nodes constantly — rendering search results, loading new messages, updating dashboards. Understanding the full lifecycle of node creation and removal prevents memory leaks and ensures smooth performance.

Real-World Use

  • A social media feed creates new post elements as the user scrolls and removes them when they scroll away
  • A modal library creates overlay elements on demand and removes them on close
  • A data grid renders thousands of rows by creating and recycling cell elements
flowchart LR
  A[Create Node] --> B[createElement]
  A --> C[createTextNode]
  B --> D[Configure Properties]
  D --> E[Insert into DOM]
  E --> F[appendChild]
  E --> G[insertBefore]
  E --> H[prepend / append]
  F --> I[Node is visible]
  I --> J[Later: remove]

Creating Elements

The createElement method creates a new element node in memory. It does not appear on the page until you insert it.

// Create a new div element
const newDiv = document.createElement('div');
newDiv.textContent = 'Hello from created element!';
newDiv.className = 'created-box';

// The element exists in memory but is not visible yet
console.log('Created element:', newDiv);
console.log('Is it on the page?', document.body.contains(newDiv));

// Now insert it into the DOM
document.body.appendChild(newDiv);
console.log('Is it on the page now?', document.body.contains(newDiv));

Expected output: The first log shows the element exists. contains returns false before appending and true after.

Creating Text and Comment Nodes

Besides elements, you can create text and comment nodes explicitly.

// Create a text node
const textNode = document.createTextNode('This is plain text content');
console.log('Text node value:', textNode.nodeValue);
console.log('Text node type:', textNode.nodeType);

// Create a comment node
const commentNode = document.createComment('This section was added dynamically');
console.log('Comment text:', commentNode.nodeValue);

// Insert them into the DOM
const container = document.querySelector('.content');
container.appendChild(commentNode);
container.appendChild(textNode);

// Text nodes are useful when you want to
// insert text without creating an element wrapper

Expected output: The console shows the text content, node types, and comment text. The document shows the text rendered without an HTML wrapper.

Inserting at Exact Positions

Different insertion methods place nodes at different positions.

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

// Append at the end
const lastItem = document.createElement('li');
lastItem.textContent = 'Last item';
list.appendChild(lastItem);

// Insert before the first child
const firstItem = document.createElement('li');
firstItem.textContent = 'First item';
list.insertBefore(firstItem, list.firstChild);

// Insert before a specific element
const middleItem = document.createElement('li');
middleItem.textContent = 'Middle item';
list.insertBefore(middleItem, list.children[2]);

// Modern relative methods
const extraItem = document.createElement('li');
extraItem.textContent = 'Extra item';

// Insert after a specific element
list.children[1].after(extraItem);

// Insert before a specific element
list.children[0].before(document.createElement('li'));

console.log('Total items:', list.children.length);

Expected output: The list grows to include items at all specified positions. The final count reflects all insertions.

Removing Nodes

Removing nodes can be done directly or through the parent.

// Modern API: direct removal
const element = document.querySelector('.to-remove');
if (element) {
    element.remove();
    console.log('Element removed');
}

// Older API: removal through parent
const another = document.querySelector('.another-to-remove');
if (another && another.parentNode) {
    another.parentNode.removeChild(another);
    console.log('Another element removed');
}

// Clear all children from a container
const container = document.querySelector('.dynamic-content');
while (container.firstChild) {
    container.removeChild(container.firstChild);
}
console.log('Container cleared:', container.children.length);

// Modern alternative: innerHTML = ''
// But this may cause memory leaks with attached event listeners

Expected output: Elements are removed from the DOM. The container's child count drops to zero.

Replacing Nodes

Replace an existing node with a new one using replaceChild or replaceWith.

const oldElement = document.querySelector('.old-widget');
const newElement = document.createElement('div');
newElement.textContent = 'New widget';
newElement.className = 'new-widget';

// Method 1: replaceChild (through parent)
if (oldElement.parentNode) {
    oldElement.parentNode.replaceChild(newElement, oldElement);
}

// Method 2: replaceWith (direct)
// oldElement.replaceWith(newElement);

console.log('Is old element in DOM?', document.body.contains(oldElement));
console.log('Is new element in DOM?', document.body.contains(newElement));

// The old element is detached from the DOM
// but still exists in memory if referenced

Expected output: The new widget replaces the old one visually. The old element is no longer in the DOM but the variable still references it.

Efficient Bulk Insertion

Creating many nodes one by one causes multiple reflow calculations. Batch inserts for performance.

// Inefficient: creates 100 reflows
const container = document.getElementById('results');

// for (let i = 0; i < 100; i++) {
//     const p = document.createElement('p');
//     p.textContent = `Item ${i}`;
//     container.appendChild(p);
// }

// Efficient: uses a document fragment (single reflow)
const fragment = document.createDocumentFragment();
for (let i = 0; i < 100; i++) {
    const p = document.createElement('p');
    p.textContent = `Item ${i}`;
    fragment.appendChild(p);
}
container.appendChild(fragment);
console.log('Inserted 100 items in one batch');

Expected output: The container shows all 100 items after a single reflow. The document fragment is an invisible temporary container that avoids multiple DOM updates.

Common Mistakes

  1. Creating a node but never inserting it — createElement creates a node in memory. If you do not insert it, it never appears and becomes garbage collected.
  2. Removing a node while iterating a live collection — Using getElementsByTagName or children while removing nodes modifies the collection and causes skipped elements.
  3. Using innerHTML to clear content with attached listeners — Setting innerHTML = '' removes elements but their event listeners may not be garbage collected if closures reference the elements.
  4. Forgetting that insertBefore requires the parent — insertBefore must be called on the parent node, not the reference node. This is a common source of errors.
  5. Creating duplicate IDs — When dynamically creating elements with IDs, ensure each ID is unique. Use class names or data attributes instead of IDs for repeated content.

Practice Questions

  1. What is the difference between removeChild and remove? removeChild is called on the parent node with the child as argument. remove is called directly on the element.
  2. Where does appendChild insert the new node? At the end of the parent's children, after the last child.
  3. Why use a document fragment for bulk inserts? The fragment is not part of the live DOM tree, so appending to it does not trigger reflow. Only the final appendChild of the fragment triggers a single reflow.
  4. Challenge: Implement a simple DOM recycling pool. Create 50 elements upfront and store them in an array. When content needs to be displayed, pull from the pool instead of creating new elements. When content is removed, return elements to the pool.

FAQ

Does remove() work in all browsers?

remove() is supported in all modern browsers. For very old browsers, use parentNode.removeChild() as a fallback.

What happens to event listeners when an element is removed?

If no other JavaScript reference to the element exists, the event listeners are garbage collected. However, closures that reference external variables may cause memory leaks.

Can I insert the same node in multiple places?

No. A node can only have one parent. If you insert the same node elsewhere, it is automatically removed from its previous location.

Is it better to remove elements or hide them with display:none?

Depends. Remove if you do not need the element again and want to free memory. Hide if you need to show it later and want to avoid recreation cost.

How do I create an element with attributes in one step?

Use document.createElement followed by setting attributes. There is no built-in createElementWithAttributes shortcut. You can write a helper function.

Mini Project

Build an infinite scrolling list. Create a container div. Write a function that generates 20 list items with random text, wraps them in a document fragment, and appends them to the container. When the user scrolls near the bottom, load 20 more items. Use efficient node creation patterns to avoid jank. Include a "Clear" button that removes all items.

What's Next

Continue with Lesson 9: innerHTML vs DOM Methods to understand when to use innerHTML and when to use DOM manipulation APIs for security and performance.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro