Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does setting textContent cause layout thrashing?

Tags:

This blog post suggests that textContent is preferable to innerText for avoiding layout thrashing. But it is focused on retrieving an element's text; for setting element text, the opposite appears to be true -- at least in the following example.

This example uses innerText and produces no layout thrashing:

<style>
    #test {
        background-color: blue;
        float: right;
        width: 100px;
        height: 100%;
    }
</style>
Test test test
<div id="test"></div>
<script>
    setInterval(function() {
        document.querySelector('#test').innerText = 'innerText';
    }, 100);
</script>

image

But replace innerText with textContent and watch it thrash:

image

Can someone explain this behavior? What can I do to avoid layout thrashing and still change an element's text in a standards-based way?

like image 696
John Avatar asked Jun 19 '13 19:06

John


People also ask

What is the function of document textContent?

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

What is the difference between innerText and textContent?

textContent gets the content of all elements, including <script> and <style> elements. In contrast, innerText only shows "human-readable" elements. textContent returns every element in the node. In contrast, innerText is aware of styling and won't return the text of "hidden" elements.


1 Answers

The issue:

You are correct! Just like you observed. Setting textContent does cause thrashing.

Here is what the DOM specification has to say:

textContent of type DOMString, introduced in DOM Level 3

This attribute returns the text content of this node and its descendants. When it is defined to be null, setting it has no effect. On setting, any possible children this node may have are removed and, if it the new string is not empty or null, replaced by a single Text node containing the string this attribute is set to.

The fix

A non thrashing way would be to get the element's text nodes and modify those instead of using textContent or innerText (which is non standard).

var test = document.getElementById("test");
var a = document.createTextNode("");
test.appendChild(a);
setInterval(function(){
    a.nodeValue = "Test test test";
},100);

Here is a working fiddle

Of course if the actual text will change, a paint will have to occur to update what you're seeing.

profile

like image 55
Benjamin Gruenbaum Avatar answered Sep 19 '22 20:09

Benjamin Gruenbaum