textContent, innerText, and innerHTMLJavaScript updates element content through three primary properties: textContent, innerText, and innerHTML. Choosing textContent for plain text prevents Cross-Site Scripting (XSS) security bugs and avoids slow browser layout recalculations.
textContent, innerText, and innerHTML| Property | Parses HTML? | Triggers Layout Reflow? | Safe for User Text? |
|---|---|---|---|
textContent |
No (escapes tags) | Minimal | Yes |
innerText |
No (escapes tags) | Yes (reads CSS visibility) | Yes |
innerHTML |
Yes (parses markup) | Yes | No (XSS risk) |
innerText hides text styled with display: none, which forces the browser to compute CSS layout first. textContent reads raw text directly from the DOM tree, making it dramatically faster and preserving hidden spans consistently.
When building new list items or cards from API data, create elements with document.createElement(), set their text with .textContent, and attach them with .append(). That workflow keeps markup clean and prevents script injection by design.
Use textContent whenever displaying user names, comments, or API strings, and prefer insertAdjacentHTML() over innerHTML += ... when appending trusted markup.
const app = document.getElementById("app");
if (app) {
const card = document.createElement("div");
const title = document.createElement("h2");
const userBio = "<img src=x onerror=alert(1)> Developer";
// Safe: textContent treats HTML tags as harmless literal text
title.textContent = userBio;
card.appendChild(title);
// Trusted static markup insertion without destroying sibling listeners
card.insertAdjacentHTML("beforeend", "<p class='note'>Profile loaded.</p>");
app.appendChild(card);
console.log("Safe textContent:", title.textContent);
console.log("Rendered innerHTML:", card.innerHTML);
}
innerHTML: An attacker can inject <img onerror="..."> scripts that steal session data. Always sanitize HTML or use textContent.el.innerHTML += "<span>New</span>": += serializes all child elements to a string and rebuilds them from scratch, destroying existing input values and attached event listeners! Use append() or insertAdjacentHTML("beforeend", ...).innerText inside tight loops: Reading or writing innerText repeatedly forces synchronous layout reflows and hurts rendering speed."<h2>Hi</h2>" to element.textContent?The browser escapes the < and > characters and renders the literal words <h2>Hi</h2> on screen instead of creating a heading element.
outerHTML?element.outerHTML reads or replaces the element itself along with its own opening and closing tags, whereas innerHTML affects only its child contents inside.
insertAdjacentHTML() better than innerHTML?insertAdjacentHTML("beforeend", html) inserts new trusted HTML without wiping and recreating existing child elements or event listeners inside the container.
Sign in to track your learning journey, earn industry-recognized certificates, and join our elite developer community.
Quick Access With
Experiment with the code from this lesson in our interactive playground.