innerHTML vs textContent
By FrontendPro Editorial Team Updated 9/26/2026
Answer
innerHTML reads and writes markup; textContent reads and writes plain text.
el.innerHTML = "<b>Hi</b>"; // renders bold text
el.textContent = "<b>Hi</b>"; // shows the characters <b>Hi</b>
Reading differs too. innerHTML returns the HTML string including tags; textContent returns only the text, from every descendant, including elements hidden with CSS.
textContent is the safe default
Assigning user input to innerHTML is the most common route to XSS:
el.innerHTML = userComment; // an <img onerror=...> executes
el.textContent = userComment; // always inert
Nothing inside textContent is ever parsed as markup, so there is no way for it to run code.
It is also faster: no HTML parser, no destroying and rebuilding the subtree.
When you genuinely need markup
Sanitise first with DOMPurify, or build the nodes explicitly:
el.replaceChildren();
const strong = document.createElement("strong");
strong.textContent = userInput;
el.append(strong);
insertAdjacentHTML carries exactly the same risk as innerHTML.
The third property
innerText is neither. It returns text as rendered — it respects CSS, so hidden elements are excluded and line breaks reflect layout. That makes it useful for copying what the user sees, but it forces a reflow to compute, so it is slower. Prefer textContent unless you specifically want rendered text.
| Parses HTML | Includes hidden text | Triggers reflow on read | |
|---|---|---|---|
innerHTML | Yes | Yes | No |
textContent | No | Yes | No |
innerText | No | No | Yes |
One more detail: assigning to innerHTML destroys and recreates all child nodes, so any event listeners attached to them are lost.
