(NOTE: This question isn't the same as the similar one above, as it is about differences between attached and detached DOM trees.)
A simple bit of HTML containing a DIV with no whitespace between its elements:
<!DOCTYPE html>
<html>
<body>
<div><h1>The Title</h1><p>A paragraph.</p><p>A second paragraph.</p></div>
</body>
<script type="text/javascript">
const div = document.querySelector("div");
console.log(div.innerText);
const clone = div.cloneNode(true);
console.log(clone.innerText);
document.body.appendChild(clone);
console.log(clone.innerText);
</script>
</html>
I output innerText
to the console three times.
The first time is that of the original DIV:
The Title
A paragraph.
A second paragraph.
The second is that of the cloned DIV, which I would expect to be the same, but is:
The TitleA paragraph.A second paragraph.
The third is again that of the cloned DIV, but after it has been added to the document, now what I would expect it to be:
The Title
A paragraph.
A second paragraph.
Why is the spacing different when it is not part of the document?
CodePudding user response:
This is a quirk of innerText for detached DOM nodes:
If the element itself is not being rendered (for example, is detached from the document or is hidden from view), the returned value is the same as the
Node.textContent
property.
This is because innerText
takes CSS into account (in this case, the display: block
properties of the tags to insert new lines (\n
)).
From the algorithm for computing innerText
, step 9 says:
If node's used value of 'display' is block-level or 'table-caption', then append 1 (a required line break count) at the beginning and end of items.
As you see, after you insert the cloned node into the DOM, then innerText
returns what the original node did because it is able to compute those CSS properties:
const div = document.querySelector("div");
console.log("Original, innerText:", JSON.stringify(div.innerText));
console.log("Original, textContent:", JSON.stringify(div.textContent));
const clone = div.cloneNode(true);
console.log("Detached clone, innerText:", JSON.stringify(clone.innerText));
console.log("Detached clone, textContent:", JSON.stringify(clone.textContent));
document.body.appendChild(clone);
console.log("Attached clone, innerText:", JSON.stringify(clone.innerText));
console.log("Attached clone, textContent:", JSON.stringify(clone.textContent));
<div><h1>The Title</h1><p>A paragraph.</p><p>A second paragraph.</p></div>