True dynamic web pages require the ability to create new elements and remove existing ones entirely through JavaScript. Whether you're building a todo list, a shopping cart, or a complex single-page application, creating and removing DOM elements is essential. JavaScript provides powerful methods like createElement(), appendChild(), and remove() to build interfaces from scratch. Let's master dynamic DOM manipulation!
Creating New Elements
The createElement() method creates a new HTML element that exists in memory but isn't yet part of the document.
Basic Element Creation
// Create a new element
let div = document.createElement('div');
let paragraph = document.createElement('p');
let button = document.createElement('button');
let image = document.createElement('img');
console.log(div); // <div></div>
// Element exists but isn't visible yet!
// It's in memory, not in the document
// Set properties before adding to DOM
paragraph.textContent = 'Hello World';
paragraph.id = 'myParagraph';
paragraph.className = 'text-style';
button.textContent = 'Click Me';
button.style.backgroundColor = 'blue';
button.style.color = 'white';
image.src = 'photo.jpg';
image.alt = 'A photo';
// Still not visible until appended to DOM!Creating Elements with Content
<!DOCTYPE html>
<html>
<body>
<div id="container"></div>
<script>
let container = document.getElementById('container');
// Create heading
let heading = document.createElement('h2');
heading.textContent = 'Welcome to My Page';
heading.style.color = 'blue';
// Create paragraph
let text = document.createElement('p');
text.textContent = 'This paragraph was created with JavaScript!';
text.classList.add('intro-text');
// Create button
let btn = document.createElement('button');
btn.textContent = 'Click Me';
btn.id = 'myButton';
// Add click listener before appending
btn.addEventListener('click', function() {
alert('Button clicked!');
});
// Still not visible! Must append to container
console.log('Elements created but not visible yet');
</script>
</body>
</html>Important: createElement() only creates the element in memory. It won't appear on the page until you append it to an element that's already in the DOM.
Appending Elements to the DOM
After creating elements, you need to add them to the document to make them visible.
appendChild() - Add Single Child
<!DOCTYPE html>
<html>
<body>
<div id="container"></div>
<script>
let container = document.getElementById('container');
// Create elements
let heading = document.createElement('h2');
heading.textContent = 'My Heading';
let paragraph = document.createElement('p');
paragraph.textContent = 'My paragraph';
// Append to container (now they're visible!)
container.appendChild(heading);
container.appendChild(paragraph);
// appendChild returns the appended node
let button = document.createElement('button');
button.textContent = 'Click';
let appendedButton = container.appendChild(button);
console.log(appendedButton); // <button>Click</button>
// Append in sequence (order matters)
let list = document.createElement('ul');
let item1 = document.createElement('li');
item1.textContent = 'Item 1';
list.appendChild(item1);
let item2 = document.createElement('li');
item2.textContent = 'Item 2';
list.appendChild(item2);
let item3 = document.createElement('li');
item3.textContent = 'Item 3';
list.appendChild(item3);
container.appendChild(list);
</script>
</body>
</html>append() - Modern Alternative (Multiple Elements)
let container = document.getElementById('container');
// append() can add multiple items at once
let h1 = document.createElement('h1');
h1.textContent = 'Title';
let p = document.createElement('p');
p.textContent = 'Paragraph';
let btn = document.createElement('button');
btn.textContent = 'Button';
// Append all at once
container.append(h1, p, btn);
// append() also accepts text strings
container.append('Some text here');
// appendChild() doesn't accept strings!
// container.appendChild('text'); // Error!
// Combine elements and text
let div = document.createElement('div');
div.append('Hello ', h1, ' World');
// append() doesn't return the appended element
let result = container.append(div);
console.log(result); // undefinedprepend() - Add at Beginning
let container = document.getElementById('container');
// Assume container already has some children
// <div id="container">
// <p>Existing paragraph</p>
// </div>
let newHeading = document.createElement('h1');
newHeading.textContent = 'New Heading';
// prepend adds at the BEGINNING
container.prepend(newHeading);
// Result:
// <div id="container">
// <h1>New Heading</h1>
// <p>Existing paragraph</p>
// </div>
// prepend can also take multiple items
container.prepend('Some text', newHeading);append() is more flexible
appendChild() (Old)
// appendChild() - older method
let container = document.getElementById('container');
let h1 = document.createElement('h1');
h1.textContent = 'Title';
let p = document.createElement('p');
p.textContent = 'Text';
// Must append one at a time
container.appendChild(h1);
container.appendChild(p);
// Only accepts nodes (not strings)
// container.appendChild('text'); // Error!
// Returns the appended node
let result = container.appendChild(h1);append() (Modern)
// append() - modern method
let container = document.getElementById('container');
let h1 = document.createElement('h1');
h1.textContent = 'Title';
let p = document.createElement('p');
p.textContent = 'Text';
// Append multiple at once
container.append(h1, p);
// Accepts strings too
container.append('Some text');
// Returns undefined
let result = container.append(h1);Inserting Elements at Specific Positions
insertBefore() - Insert Before Element
<!DOCTYPE html>
<html>
<body>
<ul id="list">
<li id="item1">Item 1</li>
<li id="item2">Item 2</li>
<li id="item3">Item 3</li>
</ul>
<script>
let list = document.getElementById('list');
let item2 = document.getElementById('item2');
// Create new item
let newItem = document.createElement('li');
newItem.textContent = 'New Item';
// Insert before item2
list.insertBefore(newItem, item2);
// Result:
// <ul>
// <li>Item 1</li>
// <li>New Item</li> β Inserted here
// <li>Item 2</li>
// <li>Item 3</li>
// </ul>
// Insert at beginning (before first child)
let firstItem = document.createElement('li');
firstItem.textContent = 'First';
list.insertBefore(firstItem, list.firstChild);
// Insert at end (before null = append)
let lastItem = document.createElement('li');
lastItem.textContent = 'Last';
list.insertBefore(lastItem, null); // Same as appendChild
</script>
</body>
</html>insertAdjacentElement() - Flexible Insertion
let target = document.getElementById('target');
let newElement = document.createElement('div');
newElement.textContent = 'New Element';
// Four positions:
// 'beforebegin' - before the target element
// 'afterbegin' - inside target, before first child
// 'beforeend' - inside target, after last child
// 'afterend' - after the target element
// Before target (as sibling)
target.insertAdjacentElement('beforebegin', newElement);
// Inside target at start
target.insertAdjacentElement('afterbegin', newElement);
// Inside target at end
target.insertAdjacentElement('beforeend', newElement);
// After target (as sibling)
target.insertAdjacentElement('afterend', newElement);
// Visual example:
// <!-- beforebegin -->
// <div id="target">
// <!-- afterbegin -->
// Existing content
// <!-- beforeend -->
// </div>
// <!-- afterend -->before() and after() - Modern Sibling Insertion
let target = document.getElementById('target');
let before = document.createElement('div');
before.textContent = 'Before';
let after = document.createElement('div');
after.textContent = 'After';
// Insert before target (as sibling)
target.before(before);
// Insert after target (as sibling)
target.after(after);
// Can insert multiple items
target.before(element1, element2, 'text');
target.after(element3, element4);
// Result:
// <div>Before</div>
// <div id="target">Target</div>
// <div>After</div>Removing Elements
remove() - Modern Way
<!DOCTYPE html>
<html>
<body>
<div id="container">
<p id="text1">Paragraph 1</p>
<p id="text2">Paragraph 2</p>
<p id="text3">Paragraph 3</p>
</div>
<button id="removeBtn">Remove Paragraph 2</button>
<script>
let removeBtn = document.getElementById('removeBtn');
let text2 = document.getElementById('text2');
removeBtn.addEventListener('click', function() {
// Remove element
text2.remove();
// Element is gone from DOM
console.log('Paragraph 2 removed');
// Can't remove again (it's already gone)
// But calling remove() on removed element doesn't error
});
// Remove multiple elements
let paragraphs = document.querySelectorAll('p');
paragraphs.forEach(p => {
// Add click to remove
p.addEventListener('click', function() {
this.remove();
});
});
</script>
</body>
</html>removeChild() - Older Way
let container = document.getElementById('container');
let child = document.getElementById('text2');
// Old way: parent removes child
container.removeChild(child);
// removeChild returns the removed element
let removed = container.removeChild(child);
console.log(removed); // Can still access it
// Remove first child
container.removeChild(container.firstChild);
// Remove last child
container.removeChild(container.lastChild);
// Remove all children (loop)
while (container.firstChild) {
container.removeChild(container.firstChild);
}
// Or simpler (modern)
container.innerHTML = ''; // Removes all childrenreplaceChild() - Replace Element
let container = document.getElementById('container');
let oldElement = document.getElementById('old');
// Create replacement
let newElement = document.createElement('div');
newElement.textContent = 'New Content';
newElement.className = 'new-style';
// Replace old with new
container.replaceChild(newElement, oldElement);
// oldElement is removed, newElement takes its place
// Modern alternative: replaceWith()
oldElement.replaceWith(newElement);
// Simpler - no need for parent referenceremove() is much simpler
removeChild() (Old)
// Old way: removeChild()
let container = document.getElementById('container');
let element = document.getElementById('item');
// Need parent to remove child
container.removeChild(element);
// More verbose
let parent = element.parentElement;
parent.removeChild(element);
// Remove all children
while (container.firstChild) {
container.removeChild(container.firstChild);
}remove() (Modern)
// Modern way: remove()
let element = document.getElementById('item');
// Remove directly (simpler!)
element.remove();
// No need for parent reference
// Just call remove() on element
// Remove all children (innerHTML)
let container = document.getElementById('container');
container.innerHTML = '';
// Or use replaceChildren()
container.replaceChildren();Cloning Elements
<!DOCTYPE html>
<html>
<body>
<div id="template" class="card">
<h3>Card Title</h3>
<p>Card content</p>
<button>Action</button>
</div>
<div id="container"></div>
<script>
let template = document.getElementById('template');
let container = document.getElementById('container');
// Clone element (shallow - no children)
let clone1 = template.cloneNode(false);
console.log(clone1.innerHTML); // Empty
// Clone element (deep - includes children)
let clone2 = template.cloneNode(true);
console.log(clone2.innerHTML); // Has h3, p, button
// Modify clone
clone2.querySelector('h3').textContent = 'New Card';
clone2.querySelector('p').textContent = 'New content';
// Append clone to container
container.appendChild(clone2);
// Create multiple cards
for (let i = 1; i <= 5; i++) {
let card = template.cloneNode(true);
card.querySelector('h3').textContent = `Card ${i}`;
card.querySelector('p').textContent = `Content for card ${i}`;
container.appendChild(card);
}
// Original template unchanged
console.log('Original template still exists');
</script>
</body>
</html>Practical Examples
Example 1: Dynamic Todo List
<!DOCTYPE html>
<html>
<head>
<style>
.todo-item {
padding: 10px;
margin: 5px 0;
background: #f0f0f0;
display: flex;
justify-content: space-between;
align-items: center;
}
.completed { text-decoration: line-through; opacity: 0.6; }
.delete-btn {
background: red;
color: white;
border: none;
padding: 5px 10px;
cursor: pointer;
}
</style>
</head>
<body>
<div>
<input type="text" id="todoInput" placeholder="Enter todo">
<button id="addBtn">Add Todo</button>
</div>
<div id="todoList"></div>
<script>
let input = document.getElementById('todoInput');
let addBtn = document.getElementById('addBtn');
let todoList = document.getElementById('todoList');
function createTodoItem(text) {
// Create container
let item = document.createElement('div');
item.className = 'todo-item';
// Create text span
let span = document.createElement('span');
span.textContent = text;
span.addEventListener('click', function() {
this.parentElement.classList.toggle('completed');
});
// Create delete button
let deleteBtn = document.createElement('button');
deleteBtn.textContent = 'Delete';
deleteBtn.className = 'delete-btn';
deleteBtn.addEventListener('click', function() {
item.remove();
});
// Assemble and return
item.appendChild(span);
item.appendChild(deleteBtn);
return item;
}
function addTodo() {
let text = input.value.trim();
if (text === '') {
alert('Please enter a todo');
return;
}
let todoItem = createTodoItem(text);
todoList.appendChild(todoItem);
input.value = '';
input.focus();
}
addBtn.addEventListener('click', addTodo);
input.addEventListener('keypress', function(e) {
if (e.key === 'Enter') {
addTodo();
}
});
</script>
</body>
</html>Example 2: Dynamic Table Builder
<!DOCTYPE html>
<html>
<head>
<style>
table { border-collapse: collapse; width: 100%; }
th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
th { background-color: #4CAF50; color: white; }
.delete-btn { background: red; color: white; border: none; padding: 5px 10px; cursor: pointer; }
</style>
</head>
<body>
<div>
<input type="text" id="name" placeholder="Name">
<input type="email" id="email" placeholder="Email">
<input type="number" id="age" placeholder="Age">
<button id="addBtn">Add User</button>
</div>
<table id="userTable">
<thead>
<tr>
<th>Name</th>
<th>Email</th>
<th>Age</th>
<th>Actions</th>
</tr>
</thead>
<tbody id="tableBody">
</tbody>
</table>
<script>
let nameInput = document.getElementById('name');
let emailInput = document.getElementById('email');
let ageInput = document.getElementById('age');
let addBtn = document.getElementById('addBtn');
let tableBody = document.getElementById('tableBody');
function createTableRow(name, email, age) {
// Create row
let tr = document.createElement('tr');
// Create cells
let nameTd = document.createElement('td');
nameTd.textContent = name;
let emailTd = document.createElement('td');
emailTd.textContent = email;
let ageTd = document.createElement('td');
ageTd.textContent = age;
let actionsTd = document.createElement('td');
// Create delete button
let deleteBtn = document.createElement('button');
deleteBtn.textContent = 'Delete';
deleteBtn.className = 'delete-btn';
deleteBtn.addEventListener('click', function() {
tr.remove();
});
actionsTd.appendChild(deleteBtn);
// Assemble row
tr.appendChild(nameTd);
tr.appendChild(emailTd);
tr.appendChild(ageTd);
tr.appendChild(actionsTd);
return tr;
}
addBtn.addEventListener('click', function() {
let name = nameInput.value.trim();
let email = emailInput.value.trim();
let age = ageInput.value.trim();
if (!name || !email || !age) {
alert('Please fill all fields');
return;
}
let row = createTableRow(name, email, age);
tableBody.appendChild(row);
// Clear inputs
nameInput.value = '';
emailInput.value = '';
ageInput.value = '';
nameInput.focus();
});
</script>
</body>
</html>Creating and Removing Elements Practice
Master dynamic DOM element creation
console.log() to see your output in the console above.Key Takeaways
createElement()creates elements in memory (not visible yet)appendChild()appends single node to parentappend()is modern, accepts multiple items and textprepend()adds elements at the beginninginsertBefore()inserts before a specific elementbefore()andafter()insert as siblingsremove()is the modern way to delete elementsremoveChild()is the older way (needs parent)cloneNode(true)creates deep copy with children- Set properties before appending for better performance
What's Next?
You now know how to create, append, insert, and remove DOM elements dynamically! This enables you to build truly dynamic interfaces where content can be added and removed based on user interactions.
In the next lesson, we'll explore Event Listeners and Event Handlingβlearning how to respond to user interactions like clicks, key presses, form submissions, and more. This is where your pages become truly interactive!
πͺ Practice Challenge:
Before moving on, try creating:
- A button that creates and appends a new paragraph on each click
- A dynamic list where items can be added and removed
- A card generator that creates styled cards from user input
- A table that dynamically adds and removes rows
- A shopping cart that adds/removes products dynamically