Changing Text, Classes, and Styles in the DOM

Course: JavaScript Beginner

Lesson 14: Changing Text, Classes, and Styles in the DOM

Level

Beginner

Estimated Reading Time

10–15 minutes

Goal

By the end of this lesson, the learner will be able to:

  • Change an element's text content and inner HTML using textContent and innerHTML
  • Add, remove, and toggle CSS classes using the classList API
  • Apply inline styles through element.style and understand when not to

Frontend Development Context

Selecting an element is only the first step. The real power of DOM manipulation is what you do next: update a message when the user submits a form, show an error label in red, add an "active" class to a nav link, toggle a sidebar open and closed, or replace placeholder text with real data from an API. These are the interactions users experience every time they use a web app.

The classList API is particularly important because it bridges the gap between JavaScript behavior and CSS styling. Instead of writing inline styles in JavaScript (which are hard to override and maintain), you use JavaScript to add or remove class names, and let your CSS stylesheet define what those classes look like. This separation of concerns is a fundamental pattern in professional frontend development.

Explanation

Changing text content: element.textContent sets or gets the text inside an element, ignoring any HTML tags. It is safe to use with user-provided data because it does not parse the content as HTML. element.innerHTML sets or gets the content including HTML markup — useful for inserting formatted content, but dangerous with untrusted input because it can execute malicious scripts.

The classList API: element.classList is an object with methods for managing CSS classes. .add("class-name") adds a class. .remove("class-name") removes it. .toggle("class-name") adds the class if it is absent, or removes it if it is present — perfect for on/off states like open menus and active filters. .contains("class-name") returns true if the class is currently applied.

Inline styles: element.style.propertyName sets an inline CSS style. CSS property names with hyphens are written in camelCase: background-color becomes element.style.backgroundColor. Inline styles have the highest CSS specificity, which makes them hard to override later. Use them sparingly — only for styles that must be computed dynamically (like animation positions or user-specified colors). Prefer classList for everything that can be expressed as a predefined CSS class.

Code Example

This example implements a notification banner that can be shown, styled, and dismissed:

const banner = document.querySelector("#notification-banner");
const bannerText = document.querySelector("#banner-message");
const closeBtn = document.querySelector("#close-banner");

function showNotification(message, type) {
  // Update text safely
  bannerText.textContent = message;

  // Set the type class (success, error, warning)
  banner.classList.remove("success", "error", "warning");
  banner.classList.add(type);
  banner.classList.remove("hidden");
}

closeBtn.addEventListener("click", function () {
  banner.classList.add("hidden");
});

// Show a success notification
showNotification("Profile updated successfully!", "success");

Code Explanation

bannerText.textContent = message safely sets the text of the banner. Using textContent ensures that even if message contains characters like < or >, they are displayed as literal text and not interpreted as HTML — which protects against cross-site scripting.

The showNotification function first removes all existing type classes (success, error, warning) to ensure only one is applied at a time. Then .add(type) applies the correct class. This pattern — remove all, then add one — is cleaner than trying to track which class was previously applied.

.classList.remove("hidden") reveals the banner by removing a CSS class that presumably sets display: none. This is the correct approach: the CSS file defines what "hidden" means visually, and JavaScript simply applies or removes that class. If the design changes later (perhaps hidden elements fade out instead of disappearing instantly), you only update the CSS — the JavaScript stays the same.

The close button's click handler adds the "hidden" class back, which hides the banner again. This toggle between "has hidden class" and "does not have hidden class" is one of the most common patterns in frontend JavaScript.

Pattern Highlights

Positive Pattern: Use classList.add(), .remove(), and .toggle() to control appearance — define what those classes mean in your CSS stylesheet, and let JavaScript only manage which classes are applied.

⚠️ Neutral Note: element.innerHTML = content is convenient for inserting HTML, but never use it with unsanitized user input. Content that contains <script> tags or event handler attributes can execute arbitrary JavaScript.

Negative Pattern: Setting many inline styles directly (el.style.color, el.style.padding, el.style.fontSize) scatters presentation logic into JavaScript and creates styles that are hard to override. Use CSS classes instead.

Common Mistakes

Mistake 1: Using innerHTML with user input

Setting innerHTML from untrusted content is a cross-site scripting (XSS) vulnerability. The browser parses and executes any HTML — including <script> tags and inline event handlers — found in the string.

const userInput = `<img src=x onerror="alert('hacked')">`;
element.innerHTML = userInput; // executes the onerror script!

// Safe alternative:
element.textContent = userInput; // displays it as plain text

Always use textContent for user-provided content. Only use innerHTML with strings you control entirely.

Mistake 2: Replacing all classes by setting className instead of using classList

Setting element.className = "new-class" replaces all existing classes, not just the one you want to change.

const card = document.querySelector(".product-card");
// Card already has classes: "product-card featured"
card.className = "highlighted"; // now only "highlighted" — lost the others!

// Correct:
card.classList.add("highlighted"); // adds without removing existing classes

Use classList.add() to add without destroying, and classList.remove() to remove a specific class.

Mistake 3: Trying to toggle a class and then immediately checking if the animation finished

classList.toggle() is synchronous — it changes the class instantly. But CSS transitions or animations triggered by that class change take time. Reading a style property right after toggling does not reflect the animated state.

menu.classList.toggle("open");
console.log(menu.offsetHeight); // reads the layout before animation completes

If you need to respond after a CSS transition ends, listen for the transitionend event on the element rather than reading layout values immediately after toggling.

Quick Recap

  • textContent sets plain text safely; innerHTML sets HTML content but must never be used with untrusted user input
  • classList.add(), .remove(), .toggle(), and .contains() manage CSS classes without affecting others
  • Prefer classList over inline element.style for appearance changes — keep CSS in stylesheets, not in JavaScript
  • Toggling a class on/off (using .toggle()) is the standard pattern for show/hide, open/close, and active/inactive states

Ready to test your understanding? Take the quiz to reinforce what you learned.

© 2026 Ant Skillsv.26.07.07-23:01