Resetting outerHTML
property of document.body
has a strange side effect: it adds extra empty <head></head>
into the DOM, just before body
:
head { display: inline; counter-increment: h; border: 1px solid; }
head:last-of-type::after { content: 'Head elements count: ' counter(h); }
[onclick]::after { content: attr(onclick); }
<button onclick="document.body.outerHTML=document.body.outerHTML"></button>
All browsers seem to be consistent in this. I've been told it is specified to be this way, but was not able to dig up authoritative standards stance about this, not even any mention in discussion archives. Do you know some background of this, or is there some technical reason it has to be this way? Any idea?
body object, it is most likely because the body has not been defined yet. If document. body is null, you most likely need to execute your code in the window. onload function.
The outerHTML attribute of the Element DOM interface gets the serialized HTML fragment describing the element including its descendants. It can also be set to replace the element with nodes parsed from the given string.
The outerHTML property sets or returns the HTML element, including attributes, start tag, and end tag.
Interesting question. Unfortunately the explanation is buried in the details of the HTML fragment parsing algorithm which is referenced from the definition of outerHTML in the DOM Parsing spec.
You'll need to follow the parser states through very carefully to see why, but in essence it works like this. With outerHTML, the parser is initialised as if it has just parsed the start tag of the given node's parent. For document.body, that's the html
element.
In the HTML parsing algorithm, when an html
start tag is parsed, the next thing the parser expects is a head
element. But because, in HTML, the start and end tags of the head element are optional, if it doesn't see a head start tag next, it infers one. So in the case of document.body.outerHTML, the next thing the parser sees is the body
start tag, and so creates an empty head element first.
Finally, once the fragment is parsed, the whole lot, including the inferred head element is added to the DOM.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With