Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Setting document.body.outerHTML creates empty heads. Why?

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?

like image 955
myf Avatar asked Oct 19 '18 08:10

myf


People also ask

Why is document body null?

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.

Can you set outerHTML?

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.

What does outerHTML return?

The outerHTML property sets or returns the HTML element, including attributes, start tag, and end tag.


1 Answers

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.

like image 132
Alohci Avatar answered Sep 19 '22 09:09

Alohci