Curriculum Series

Adding, removing, and mutating DOM elements in vanilla JS

Adding, removing, and mutating DOM elements in vanilla JS

Adding, removing, and mutating DOM elements in vanilla JS

JavaScript

TL;DR

The DOM gives you a small set of primitives: createElement to build nodes, append/appendChild to insert them, remove/removeChild to take them out, and a handful of APIs to change content and attributes. Master these and you can make any page dynamic without a framework.

Creating and inserting

JAVASCRIPT
1// Create a new element
2const paragraph = document.createElement('p');
3paragraph.textContent = 'Hello, world!';
4paragraph.className = 'greeting';
5
6// Add it to the page
7document.body.appendChild(paragraph);

Insertion alternatives worth knowing:

JAVASCRIPT
1const container = document.querySelector('#container');
2
3// append — adds to the end (can add multiple items and text)
4container.append(element1, element2, 'some text');
5
6// prepend — adds to the beginning
7container.prepend(element);
8
9// before / after — adds next to the element
10existingElement.before(newElement);
11existingElement.after(newElement);
12
13// insertAdjacentHTML — inserts HTML string at a specific position
14container.insertAdjacentHTML(
15 'beforeend',
16 '<p>New paragraph</p>'
17);

append/prepend are the modern go-tos — they accept multiple nodes and raw strings, unlike the older appendChild.

Removing

JAVASCRIPT
1// Modern way — call remove() on the element
2const element = document.querySelector('#old-item');
3element.remove();
4
5// Older way — remove through the parent
6const parent = document.querySelector('#list');
7const child = document.querySelector('#old-item');
8parent.removeChild(child);

Mutating

Content:

JAVASCRIPT
1element.textContent = 'New text'; // safe, plain text
2element.innerHTML = '<strong>Bold</strong>'; // parses HTML

Reach for textContent by default — innerHTML with untrusted input is an XSS vector.

Attributes:

JAVASCRIPT
1element.setAttribute('data-id', '42');
2element.getAttribute('data-id'); // "42"
3element.removeAttribute('data-id');
4
5// Or use properties directly
6element.id = 'my-element';
7element.className = 'active';

Inline styles:

JAVASCRIPT
1element.style.color = 'red';
2element.style.fontSize = '16px';
3element.style.display = 'none';

Classes (prefer this over mashing className strings):

JAVASCRIPT
1element.classList.add('active');
2element.classList.remove('active');
3element.classList.toggle('active');
4element.classList.contains('active'); // true/false

Swapping elements

JAVASCRIPT
1const oldElement = document.querySelector('#old');
2const newElement = document.createElement('div');
3newElement.textContent = 'I am new';
4
5oldElement.replaceWith(newElement);

Cloning

JAVASCRIPT
1const original = document.querySelector('.card');
2
3// Shallow clone (no children)
4const clone = original.cloneNode(false);
5
6// Deep clone (includes all children)
7const deepClone = original.cloneNode(true);
8
9document.body.appendChild(deepClone);

Interview Tip

Show you know both the modern and legacy APIs — append/remove/replaceWith alongside the older appendChild/removeChild. Reaching for classList rather than hand-editing className is a small signal that you've done this at scale.

Why interviewers ask this

Even in a React-first world, every senior frontend engineer should be able to drop down to raw DOM APIs. This question checks whether you understand what frameworks are doing for you — and whether you could debug or write a 3rd-party integration that needs direct DOM access.

Finished reading?

Mark this topic as solved to track your progress.