Once you've selected an element, you can change anything about it: its text, classes, styles and attributes. You can also create brand-new elements and remove old ones. This is how interactive websites update what you see without reloading the page.
DOM manipulation is where your JavaScript becomes visible to visitors. A basket counter that goes up, an error message that appears under a form field and a menu that opens are all small changes to the DOM. This lesson covers the handful of tools that handle almost all of those jobs, and the safe way to use them.
Changing text and HTML
el.textContent = "Hi"sets plain text. It's safe, because any<tags>in the text are displayed as text rather than turned into elements.el.innerHTML = "<strong>Hi</strong>"sets HTML. It's powerful, but never use it with text typed by visitors, because they could inject harmful code. This kind of attack is called cross-site scripting (XSS).input.valuereads or sets what's in a form field.
When in doubt, use textContent. It's also faster, because the browser doesn't have to interpret any HTML.
Changing styles with classList
el.classList.add("active");
el.classList.remove("hidden");
el.classList.toggle("open"); // add if missing, remove if present
el.classList.contains("open"); // true or falseDefine how each state looks in CSS, then switch classes in JavaScript. Keeping the styling in your stylesheet means a designer can change the look of the "open" menu without touching any JavaScript.
Inline styles and attributes
el.style.backgroundColor = "gold"sets an inline style. CSS property names become camelCase in JavaScript.el.setAttribute("aria-expanded", "true"),el.getAttribute("href")andel.removeAttribute("disabled")work with any attribute.- Many attributes are also properties:
img.src,link.hrefandbutton.disabled = true. data-*attributes appear inel.dataset, sodata-price="9"becomesel.dataset.price.
Inline styles suit values that are calculated, such as the width of a progress bar. For on/off states, classes are cleaner.
Creating, adding and removing elements
const li = document.createElement("li");
li.textContent = "New task";
list.append(li); // add as the last child
list.prepend(li); // or as the first child
li.remove(); // delete itappend can take several elements or strings at once, and el.replaceChildren() empties an element completely. An element you create exists only in memory until you add it to the page.
DOM Manipulation Syntax
DOM changes
el.textContent = "text";
el.classList.toggle("active");
el.style.color = "tomato";
el.setAttribute("title", "Hello");
const item = document.createElement("li");
parent.append(item);
item.remove();DOM Manipulation Summary
textContentsets plain text safely; avoidinnerHTMLwith anything a visitor typed.- Use
classListto add, remove and toggle classes defined in CSS. style,setAttributeanddatasetchange styles and attributes.createElement,append,prependandremoveadd and delete elements.- Rebuild the page from your data whenever the data changes.
DOM Manipulation Examples
Each example runs in the page. Edit the code and press Run to see what changes.
Text, classes and styles
<div class="alert" id="alert">Saving…</div>
<button id="done">Mark as saved</button>
<style>
.alert { padding: 10px; border-radius: 8px; background: #fff1c2; font-family: sans-serif; }
.alert.success { background: #d6f4e4; color: #0e7c4a; font-weight: bold; }
</style>const alertBox = document.querySelector("#alert");
const button = document.querySelector("#done");
alertBox.textContent = "Saved! ✅";
alertBox.classList.add("success");
alertBox.style.borderLeft = "5px solid #17a865";
button.disabled = true;
button.textContent = "Done";
console.log(alertBox.classList.contains("success"));Line-by-line explanation
- Line 4Replace the text.
- Line 5Add a class, and the CSS for
.alert.successtakes over. - Line 6An inline style.
border-leftbecomesborderLeftin JavaScript. - Lines 8 to 9Properties like
disabledandtextContentwork on buttons too.
Building a list from an array
<h3>Reading list</h3>
<ul id="books"></ul>const books = [
{ title: "The Hobbit", read: true },
{ title: "Dune", read: false },
{ title: "Matilda", read: true },
];
const list = document.querySelector("#books");
for (const book of books) {
const li = document.createElement("li");
li.textContent = book.title;
if (book.read) {
li.textContent += " ✓";
li.style.color = "gray";
}
list.append(li);
}
console.log(list.children.length, "books shown");Line-by-line explanation
- Lines 1 to 5The data.
- Lines 10 to 18For each book: create an
li, fill it in, style it, and append it. - Line 12
textContentis safe even if a title contained<characters.
Removing and toggling
Click the items to toggle them; the button removes completed ones.
<ul id="todo">
<li>Feed cat</li>
<li class="done">Buy stamps</li>
<li>Call Nan</li>
</ul>
<button id="clear">Clear completed</button>
<style>
li { cursor: pointer; }
.done { text-decoration: line-through; opacity: 0.5; }
</style>const items = document.querySelectorAll("#todo li");
items.forEach(li => {
li.addEventListener("click", () => li.classList.toggle("done"));
});
document.querySelector("#clear").addEventListener("click", () => {
document.querySelectorAll("#todo .done").forEach(li => li.remove());
console.log("Remaining:", document.querySelectorAll("#todo li").length);
});Line-by-line explanation
- Line 4
toggleaddsdoneif missing, removes it if present. - Line 8Find every completed item and delete it.
Common DOM Manipulation Mistakes
innerHTML with user input
comment.innerHTML = userText; // a user could type <img src=x onerror="…">comment.textContent = userText;Treat anything a user typed as text, never as HTML.
Styling with lots of inline styles
box.style.background = "red";
box.style.color = "white";
box.style.border = "2px solid black";box.classList.add("is-error");
/* .is-error { background: red; color: white; border: 2px solid black; } */className overwriting classes
el.className = "active"; // removes every other class!el.classList.add("active");DOM Manipulation in Real Projects
What this powers
Adding an item to a basket and updating the counter, showing an error under a form field, switching tabs, opening a mobile menu, showing search results as you type and switching dark mode on and off are all DOM manipulation, usually triggered by events.
DOM Manipulation Exercises
Answer each one and check it instantly. If you get stuck, open the hint before the answer.
Change the text safely and turn on the open class.
const menu = document.querySelector(".menu");
menu. = "Menu (open)";
menu.classList.("open");
textContent sets text; classList.add adds a class.Which is safe to use with text a user typed?
What does el.classList.toggle("dark") do?
The code should add three <li> items to the list and make the title red. Fix the mistakes.
<h3 id="title">Colours</h3>
<ul id="colors"></ul>const colors = ["Red", "Green", "Blue"];
const list = document.querySelector("#colors");
colors.forEach(c => {
const li = document.createElement("<li>");
li.textContent = c;
list.append;
});
document.querySelector("#title").style.colour = "red";- Three list items exist
- Items have the right text
- Title is red
- No errors
DOM Manipulation Quiz
3 questions to check what you learned.
Which method creates a new element?
- document.newElement("p")
- document.make("p")
- new Element("p")
- document.createElement("p")
How do you read
data-price="12"from an element?- el.price
- el.data("price")
- el.attributes.price
- el.dataset.price
In JavaScript, what is the CSS property
font-sizecalled onel.style?- fontSize
- font-size
- FontSize
- font_size
DOM Manipulation Challenge
Render a scoreboard
Given the players array:
- For each player, create an
<li>with text likeAna: 120 - Add the class
leaderto theliof the player with the highest score - Append them all to
#board - Set the
#counttext to3 players
<ol id="board"></ol>
<p id="count"></p>
<style>.leader { font-weight: bold; color: #17a865; }</style>const players = [
{ name: "Ana", score: 120 },
{ name: "Bo", score: 340 },
{ name: "Cal", score: 90 },
];
- Three items in the board
- Item text looks like "Ana: 120"
- Only Bo is the leader
- Count says "3 players"