text text everywhere

Next up in my series of things I need to know but always forget is the difference between JavaScript's Element.innerText and Node.textContent.

The fundamental difference when reading is textContent rips the text out of anything, no matter what, while innerText is more careful. It returns text as it's visible to the user, so no scripts, styles or stuff hidden by CSS, and with whitespace collapsed. This can be more expensive (but not really for the scale I'm working on).

In practice, this means that innerText is good for getting text as it appears to the user, while textContent is for getting text as it's written in source. This comes with a big caveat though: innerText does not read pseudo-elements' contents.

For example, calling each of innerText and textContent on

<div
          id="wrapper">
       <p>
       it was<br>
       <span hidden>not</span>
       a <i></i>
          night
       </p>
       <style>
       i::after {
       content: "dark and stormy";
       }
       </style>
      </div>

which renders

it was
a dark and stormy night

will return

wrapper.innerText
      'it was\na night'
      
      wrapper.textContent
      '\n \n it was\n not\n a night\n \n
          \n i::after {\n content: "dark and stormy";\n }\n
          \n'

Now there's only one question left: what happens when we set to them? In a similar way to when reading, innerText will preserve linebreaks, inserting <br>, while textContent ignores them. White space is preserved by both, though the HTML parser will compress it unless the element has white-space: pre set.

As with most of the posts under my learning tag, explaining this is more for my benefit than yours – unless you happen to be future me who's forgotten the difference again, in which case, hi me. So if you want a more sound explanation, see MDN's explanation of the differences.