363

What is the difference between textContent and innerText in JavaScript?

Can I use textContent as follows:

var logo$ = document.getElementsByClassName('logo')[0];
logo$.textContent = "Example";
u-ways
  • 6,136
  • 5
  • 31
  • 47
J K
  • 4,883
  • 6
  • 15
  • 24
  • 1
    @Pointy what is the one that all browsers support? – Yehia Awad Feb 04 '16 at 22:47
  • 14
    A [good blog post](http://www.kellegous.com/j/2013/02/27/innertext-vs-textcontent/) about it – webketje Feb 04 '16 at 22:49
  • There isn't one. You have to include code to check which exists and then use that one. – Pointy Feb 04 '16 at 22:49
  • 9
    @Pointy please refer to the blog post I pointed to. Your statement is incorrect, there is a difference. – webketje Feb 04 '16 at 22:55
  • jQuery's `.text()` method is your friend here: http://api.jquery.com/text/ – Jeremy Ray Brown Feb 04 '16 at 23:00
  • @Tyblitz yes you're right, but the reason that sites use `innerText` is because *there's no choice* on older IE versions. – Pointy Feb 04 '16 at 23:04
  • 10
    `innerText` and `textContent` are decidedly not the same. White-space occurences in node content will cause the two properties yield different content, and so will occurences of `br` elements and other block-level rendered descendants. – Armen Michaeli Apr 27 '19 at 14:58
  • Does this answer your question? [innerText vs innerHTML vs label vs text vs textContent vs outerText](https://stackoverflow.com/q/24427621/90527) – outis Nov 04 '21 at 20:44
  • It appears to me that none of the answers has fully addressed whether there is any difference in the setters in the case of an HTMLElement, where both are present. By comparing the MDN description of the setters for [textContent](https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent) and for [innerText](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/innerText) it seems not. But maybe somebody has more insight? – Sebastian Mar 24 '23 at 18:14
  • I figured out in the meantime, that using `innerText` as setter turns `\n` into `
    `. I was aware of the other direction in the getter, but I had not expected that markup is produced when setting text. For `textContent` this is of course not the case.
    – Sebastian Mar 25 '23 at 08:22

10 Answers10

458

The key differences between innerText and textContent are outlined very well in Kelly Norton's blogpost: innerText vs. textContent. Below you can find a summary:

  1. innerText was non-standard, textContent was standardized earlier.
  2. innerText returns the visible text contained in a node, while textContent returns the full text. For example, on the following HTML <span>Hello <span style="display: none;">World</span></span>, innerText will return 'Hello', while textContent will return 'Hello World'. For a more complete list of differences, see the table at http://perfectionkills.com/the-poor-misunderstood-innerText/ (further reading at 'innerText' works in IE, but not in Firefox).
  3. As a result, innerText is much more performance-heavy: it requires layout information to return the result.
  4. innerText is defined only for HTMLElement objects, while textContent is defined for all Node objects.

Be sure to also have a look at the informative comments below this answer.

textContent was unavailable in IE8-, and a bare-metal polyfill would have looked like a recursive function using nodeValue on all childNodes of the specified node:

function textContent(rootNode) {
  if ('textContent' in document.createTextNode(''))
    return rootNode.textContent;

  var childNodes = rootNode.childNodes,
      len = childNodes.length,
      result = '';
  
  for (var i = 0; i < len; i++) {
    if (childNodes[i].nodeType === 3)
      result += childNodes[i].nodeValue;
    else if (childNodes[i].nodeType === 1) 
      result += textContent(childNodes[i]);
  }

  return result;
}
Boris Verkhovskiy
  • 14,854
  • 11
  • 100
  • 103
webketje
  • 10,376
  • 3
  • 25
  • 54
  • 74
    Also worth noting: `innerText` will turn `
    ` elements into newline characters, while `textContent` will just ignore them. So 2 words with only a `
    ` element between them (and no spaces) will be concatenated when using `textContent`
    – Jelle De Loecker Mar 15 '18 at 10:19
  • 23
    Then is there any difference when the setter is used? Like `elem.textContent = 'foobar'` v.s. `elem.innerText = 'foobar'` – Franklin Yu Feb 28 '19 at 15:21
  • 14
    Another difference in behavior between `innerText` and `textContent`: If you change the `text-transform` of an element by CSS, it will affect the result of 'innerText', but not the result of `textContent`. For example: `innerText` of `
    Hello World
    ` will be "HELLO WORLD", while `textContent` will be "Hello World".
    – Kobi Dec 16 '19 at 07:45
  • 1
    Regarding to point "3" (performance). I did a quick test and I don't see that it's true. `let allElements = [...document.getElementsByTagName('*')]; t1 = performance.now(); for(let i=0; i – Shimon S Oct 12 '20 at 08:22
  • 4
    @ShimonS *innerText is much more performance-heavy* is true, but is to be taken relatively: if `innerText` is 100x slower than `textContent` on avg, and `textContent` takes 1/1000 of a millisecond per op, 1/10th of a millisecond will still *feel* fast to humans. Furthermore a meaningful comparison between the 2 can only be one where the element contains a lot of hidden stuff like ` – webketje Oct 12 '20 at 18:33
  • @Kobi, I don't see this is true, https://stackblitz.com/edit/js-b86gal?file=index.html – Normal Dec 11 '22 at 21:29
  • If you're creating a search function within the DOM, `textContent` is infinitely better. https://stackoverflow.com/questions/72874515/is-there-any-way-to-optimize-my-client-side-search-function – Douglas Vicentini Dec 30 '22 at 11:04
  • 1
    @Normal Maybe I wasn't clear enough. I've edited your example here: https://stackblitz.com/edit/js-hv6fwn?file=index.js . Check the console output after clicking the button. – Kobi Jan 19 '23 at 08:19
  • @Kobi, yep, now I see – Normal Jan 20 '23 at 06:47
58

textContent is the only one available for text nodes:

var text = document.createTextNode('text');

console.log(text.innerText);    //  undefined
console.log(text.textContent);  //  text

In element nodes, innerText evaluates <br> elements, while textContent evaluates control characters:

var span = document.querySelector('span');
span.innerHTML = "1<br>2<br>3<br>4\n5\n6\n7\n8";
console.log(span.innerText); // breaks in first half
console.log(span.textContent); // breaks in second half
<span></span>

span.innerText gives:

1
2
3
4 5 6 7 8

span.textContent gives:

1234
5
6
7
8

Strings with control characters (e. g. line feeds) are not available with textContent, if the content was set with innerText. The other way (set control characters with textContent), all characters are returned both with innerText and textContent:

var div = document.createElement('div');
div.innerText = "x\ny";
console.log(div.textContent);  //  xy
johannchopin
  • 13,720
  • 10
  • 55
  • 101
Martin Wantke
  • 4,287
  • 33
  • 21
41

For those who googled this question and arrived here. I feel the most clear answer to this question is in MDN document: https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent.

You can forgot all the points that may confuse you but remember 2 things:

  1. When you are trying to alter the text, textContent is usually the property you are looking for.
  2. When you are trying to grab text from some element, innerText approximates the text the user would get if they highlighted the contents of the element with the cursor and then copied to the clipboard. And textContent gives you everything, visible or hidden, including <script> and <style> elements.
Northern
  • 2,338
  • 1
  • 17
  • 20
  • "Moreover, since innerText takes CSS styles into account, reading the value of innerText triggers a reflow to ensure up-to-date computed styles. (Reflows can be computationally expensive, and thus should be avoided when possible.)" "Reflow happens when a browser must process and draw part or all of a webpage again, such as after an update on an interactive site." https://developer.mozilla.org/en-US/docs/Glossary/Reflow innerText <-> ReFlow relationship. Those MDN articles is more explanatory than other answers. – EGurelli Sep 27 '21 at 04:37
  • 1
    @Northern from the MDN link you provided I couldn't determine any difference in the setters, but only in the getters. At least when both are present. Would you agree? – Sebastian Mar 24 '23 at 18:19
28

Both innerText & textContent are standardized as of 2016. All Node objects (including pure text nodes) have textContent, but only HTMLElement objects have innerText.

While textContent works with most browsers, it does not work on IE8 or earlier. Use this polyfill for it to work on IE8 only. This polyfill will not work with IE7 or earlier.

if (Object.defineProperty 
  && Object.getOwnPropertyDescriptor 
  && Object.getOwnPropertyDescriptor(Element.prototype, "textContent") 
  && !Object.getOwnPropertyDescriptor(Element.prototype, "textContent").get) {
  (function() {
    var innerText = Object.getOwnPropertyDescriptor(Element.prototype, "innerText");
    Object.defineProperty(Element.prototype, "textContent",
     {
       get: function() {
         return innerText.get.call(this);
       },
       set: function(s) {
         return innerText.set.call(this, s);
       }
     }
   );
  })();
}

The Object.defineProperty method is availabe in IE9 or up, however it is available in IE8 for DOM objects only.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty

https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent

Richard Hamilton
  • 25,478
  • 10
  • 60
  • 87
  • 2
    Here's the spec for it, too: https://www.w3.org/TR/DOM-Level-3-Core/core.html Also the (very old) browser support table (http://www.webdevout.net/browser-support-dom#dom3core) suggests, that it's supported for IE9+, so for IE8 and older, `innerText` is your friend. – geekonaut Feb 04 '16 at 22:55
  • Actually, it's a better idea to either not support ie8 or use the polyfill. I posted the polyfill in my post – Richard Hamilton Feb 04 '16 at 22:59
  • 1
    How can that polyfill work in IE8 when it didn't support `Object.defineProperty()`? – Pointy Feb 04 '16 at 23:06
  • Just took a look at the MDN documentation. It says this `In Internet Explorer 8 only on DOM objects and with some non-standard behaviors.` – Richard Hamilton Feb 04 '16 at 23:09
  • 2
    why don't you update your answer? https://html.spec.whatwg.org/multipage/dom.html#the-innertext-idl-attribute – caub Jan 18 '18 at 08:48
  • 3
    Here is a quote from MDN about innerText - "This feature was originally introduced by Internet Explorer, and was formally specified in the HTML standard in 2016 after being adopted by all major browser vendors." – the chad May 02 '19 at 23:38
8

textContent is supported by most browsers. It is not supported by ie8 or earlier, but a polyfill can be used for this

The textContent property sets or returns the textual content of the specified node, and all its descendants.

See http://www.w3schools.com/jsref/prop_node_textcontent.asp

Richard Hamilton
  • 25,478
  • 10
  • 60
  • 87
Jeremy Ray Brown
  • 1,499
  • 19
  • 23
7

Aside from all the differences that were named in the other answers, here is another one which I discovered only recently:

Even though the innerText property is said to've been standardised since 2016, it exhibits differences between browsers: Mozilla ignores U+200E and U+200F characters ("lrm" and "rlm") in innerText, while Chrome does not.

console.log(document.getElementById('test').textContent.length);
console.log(document.getElementById('test').innerText.length);
<div id="test">[&#x200E;]</div>

Firefox reports 3 and 2, Chrome reports 3 and 3.

Not sure yet if this is a bug (and if so, in which browser) or just one of those quirky incompatibilities which we have to live with.

Mr Lister
  • 45,515
  • 15
  • 108
  • 150
4

textContent returns full text and does not care about visibility, while innerText does.

<p id="source">
    <style>#source { color: red; }</style>
    Text with breaking<br>point.
    <span style="display:none">HIDDEN TEXT</span>
</p>

Output of textContent:

#source { color: red; } Text with breakingpoint. HIDDEN TEXT

Output of innerText ( note how innerText is aware of tags like <br>, and ignores hidden element ):

Text with breaking point.
Milan Chandro
  • 2,342
  • 1
  • 18
  • 25
1

Another useful behavior of innerText compared to textContent is that newline characters and multiple spaces next to each other will be displayed as one space only, which can be easier to compare a string.

But depending on what you want, firstChild.nodeValue may be enough.

baptx
  • 3,428
  • 6
  • 33
  • 42
0
document.querySelector('h1').innerText/innerHTML/textContent 

.querySelector('h1').innerText - gives us text inside. It sensitive to what is currently being displayed or staff that's being hidden is ignored.

.querySelector('h1').textContent - it's like innerText but it does not care about what is being displayed or what's actually showing to user. It will show all.

.querySelector('h1').innerHTML = <i>sdsd</i> Will work* - retrieves full contents, including the tag names.

CennoxX
  • 773
  • 1
  • 9
  • 20
vitoboski
  • 203
  • 2
  • 3
-3

innerHTML will execute even the HTML tags which might be dangerous causing any kind of client-side injection attack like DOM based XSS. Here is the code snippet:

<!DOCTYPE html>
<html>
    <body>
        <script>
            var source = "Hello " + decodeURIComponent("<h1>Text inside gets executed as h1 tag HTML is evaluated</h1>");  //Source
            var divElement = document.createElement("div");
            divElement.innerHTML = source;  //Sink
            document.body.appendChild(divElement);
        </script>
    </body>
</html>

If you use .textContent, it will not evaluate the HTML tags and print it as String.

<!DOCTYPE html>
<html>
    <body>
        <script>
            var source = "Hello " + decodeURIComponent("<h1>Text inside will not get executed as HTML</h1>");  //Source
            var divElement = document.createElement("div");
            divElement.textContent = source;  //Sink
            document.body.appendChild(divElement);
        </script>
    </body>
</html>

Reference: https://www.scip.ch/en/?labs.20171214