textContent in JavaScript: reading and writing an element's text

textContent gives you the raw text of a DOM element, both to read and to write, and closes the door that innerHTML leaves wide open.
3 min read
Believemy logo

Showing a name, a price, an error message: a large share of interface work is about replacing text inside a page that is already on screen. The DOM offers three properties for that, and they do not behave the same way at all.

The safest of the three is also the simplest. It only knows about text, and that is exactly what makes it the sensible default.


Definition

textContent is a property available on every DOM node. When read, it returns the concatenation of the text held by the element and all of its descendants, with tags removed. When written to, it replaces the entire content of the element with a single string.

JAVASCRIPT
const title = document.querySelector("h1");

console.log(title.textContent);   // "Hello Camille"

title.textContent = "Hello Alex";
// the h1 now holds a single text node

The value read is always a String. An empty element returns an empty string, never null, which saves you from testing for absence before working with the result.


Three properties, three results

On the same element, the three content-reading properties return three different values. The table compares them across three columns: the property, what it returns, and what it costs.

PropertyWhat it returns when readWhat to keep in mind
textContentAll the text, including text hidden by CSSThe fastest of the three
innerTextThe text as it appears on screenForces the browser to recompute layout
innerHTMLThe full markup, tags includedParses HTML when you write to it

That third row alone explains why innerHTML calls for caution: whatever you hand it becomes structure, not text.


Writing text without parsing HTML

The difference turns into a security question as soon as the string comes from somewhere else: a form field, an API response, a URL parameter.

JAVASCRIPT
const area = document.getElementById("message");
const input = '<img src=x onerror="alert(1)">';

area.textContent = input;
// shows the characters as they are, nothing runs

area.innerHTML = input;
// the browser builds an image and triggers the attached code

No escaping helper is needed in the first case: the property never builds a tag, whatever you pass to it.

Good to know

Writing to textContent destroys every existing child node. If the element held buttons with listeners registered through addEventListener(), those listeners go away with them.


Frequently asked questions

Question

textContent or innerText, which one should I pick?

textContent by default: it is faster and its result does not depend on the CSS in effect. innerText is only worth it when you need the visible text, the one a visitor would copy with the mouse, with hidden elements left out and rendered line breaks kept. That convenience costs a layout recalculation on every read.


Question

How do I append text without erasing the rest?

An assignment replaces everything, so concatenating onto the existing value works but rebuilds the content for nothing. The insertAdjacentText method inserts a string at a precise position, and createElement() lets you add a real node next to the others. Both leave whatever was already there untouched.


Question

Why does my read contain spaces and line breaks?

Because the indentation of the HTML file is text too. An element written across three lines holds text nodes made of whitespace, and the property returns them faithfully. A plain trim() on the value you read settles the matter in almost every situation.

Related terms

Discover our javaScript glossary

Every word of JavaScript explained simply: keywords, built-in objects, methods, errors and concepts. Clear definitions and examples that actually run, to learn and to troubleshoot.

Share this article

Want to help us? Share this article on your networks or even better: on your site, in an article or in your newsletter.