JavaScript course menu
Creating and Removing DOM Elements: createElement, append, remove and Templates
Learn to add and remove elements with JavaScript: createElement, setting text and attributes, append, prepend, before, after and insertAdjacentHTML, removing elements, rendering lists from arrays, DocumentFragment, and the template element.
On this page
Real interfaces add and remove content all the time: new chat messages, items added to a cart, search results. JavaScript builds elements and inserts them into the DOM.
Creating an element#
Three steps: create, configure, insert:
<ul id="list">
<li>Existing item</li>
</ul>const li = document.createElement("li"); // 1. create
li.textContent = "Added with JavaScript"; // 2. configure
li.className = "new";
li.style.color = "seagreen";
document.querySelector("#list").append(li); // 3. insertA created element is not visible until it is inserted into the document.
Where to insert#
<p>Before the list</p>
<ul id="list"><li>Middle</li></ul>
<p>After the list</p>const list = document.querySelector("#list");
const make = (text) => Object.assign(document.createElement("li"), { textContent: text });
list.append(make("append: last child"));
list.prepend(make("prepend: first child"));
list.before("before: a text node before the list");
list.after("after: a text node after the list");They accept elements and plain strings (which become text nodes) and can take several at once. Inserting an element that is already in the page moves it.
Removing elements#
<ul id="list">
<li>Keep me</li>
<li class="old">Remove me</li>
<li>Keep me too</li>
</ul>
<button id="clean">Remove old items</button>
<button id="clear">Clear list</button>document.querySelector("#clean").addEventListener("click", () => {
document.querySelectorAll("#list .old").forEach((li) => li.remove());
});
document.querySelector("#clear").addEventListener("click", () => {
document.querySelector("#list").replaceChildren(); // remove all children
});element.remove()removes the element itself.parent.replaceChildren()with no arguments removes all children; with arguments, it replaces them.
Rendering a list from data#
A very common task: turn an array of data into elements:
<h3>Courses</h3>
<ul id="courses"></ul>const courses = [
{ name: "HTML", lessons: 46 },
{ name: "CSS", lessons: 47 },
{ name: "JavaScript", lessons: 56 },
];
const list = document.querySelector("#courses");
const items = courses.map((course) => {
const li = document.createElement("li");
const strong = document.createElement("strong");
strong.textContent = course.name;
li.append(strong, ` (${course.lessons} lessons)`);
return li;
});
list.replaceChildren(...items);Building elements and setting textContent is safe even if the data comes from users. (Inserting all items in one replaceChildren call, or through a DocumentFragment, also means the browser updates the layout once instead of once per item.)
insertAdjacentHTML#
For trusted markup, insertAdjacentHTML inserts HTML at a position without wiping the existing content (unlike innerHTML +=):
list.insertAdjacentHTML("beforeend", "<li><em>Static, trusted markup</em></li>");
// positions: "beforebegin", "afterbegin", "beforeend", "afterend"The same XSS warning as innerHTML applies: never insert user input this way.
The template element#
For larger repeated structures, write the markup once in a <template>. Its contents are not shown on the page; you clone them in JavaScript:
<template id="card-template">
<article style="border: 1px solid #ccc; border-radius: 8px; padding: 8px 12px; margin-bottom: 8px">
<h3 class="name"></h3>
<p class="role"></p>
</article>
</template>
<div id="team"></div>const team = [
{ name: "Asha", role: "Front-end developer" },
{ name: "Ravi", role: "Data analyst" },
];
const template = document.querySelector("#card-template");
for (const person of team) {
const card = template.content.cloneNode(true);
card.querySelector(".name").textContent = person.name;
card.querySelector(".role").textContent = person.role;
document.querySelector("#team").append(card);
}template.content.cloneNode(true) makes a deep copy of the template's contents each time.
Frameworks#
Creating and updating many elements by hand gets complicated as an app grows. Frameworks such as React, Vue and Svelte let you describe what the page should look like for given data, and update the DOM for you. They are built on exactly the operations in this lesson.
Practice#
Practice exercise
Build a simple to-do list: a text input, an "Add" button that adds the trimmed text as a new list item (ignore empty input and clear the field afterwards), and a "Delete" button inside each item that removes it.
Show solution
<input id="task" placeholder="New task">
<button id="add">Add</button>
<ul id="todo"></ul>const input = document.querySelector("#task");
const list = document.querySelector("#todo");
document.querySelector("#add").addEventListener("click", () => {
const text = input.value.trim();
if (text === "") return;
const li = document.createElement("li");
const del = document.createElement("button");
del.textContent = "Delete";
del.addEventListener("click", () => li.remove());
li.append(text + " ", del);
list.append(li);
input.value = "";
input.focus();
});Key takeaway#
Finished this lesson?