One of the lesser known HTML5 JavaScript goodies is the document.head
DOM tree accessor, which is a more efficient (and easier to type) alternative to document.getElementsByTagName('head')[0]
.
The
head
element of a document is the firsthead
element that is a child of thehtml
element, if there is one, ornull
otherwise. Thehead
attribute, on getting, must return thehead
element of the document (ahead
element ornull
).
Native support for document.head
is very easy to detect:
if (document.getElementsByTagName('head')[0] === document.head) {
// Native support
}
Emulating it is also very straightforward. Just put the following snippet in your JavaScript code:
document.head = document.head || document.getElementsByTagName('head')[0];
If you don’t care about JSLint booing at your code, you could also do this instead (which is slightly more efficient):
document.head || (document.head = document.getElementsByTagName('head')[0]);
After that, go ahead and use document.head
all you want :)
Comments
Paul Irish wrote on :
If you wanna be even more efficient:
:)
Mathias wrote on :
Paul Irish: Nice! Too bad JSLint complains about it:
Framp wrote on :
Simple is beautiful.
Raynos wrote on :
Curly braces are beautiful.
Adrusi wrote on :
Block scope is beautiful.
Federico wrote on :
Adrusi: How is that even needed? Care to help us understand (via links, search keywords, etc.)?
Lea Verou wrote on :
The problem with these polyfills is that on new iframes
document.head
still won’t exist, so they’re imperfect. Not sure how to solve that in a sensible manner though, but I’d really like to see adocument.head
polyfill one can really rely on.Mathias wrote on :
Lea: That’s a fair point.
Personally I’m fine with just using the above snippet (it’s not really a polyfill in the strict sense of the word) once for every frame I need it for. Most of the time I need a reference to the
<head>
element in a given document, I end up caching it like this:It’s so small and fast it doesn’t really hurt to repeat it for a different frame when needed.
Matt wrote on :
Federico: Block scope is completely pointless in that case. There's nothing to be scoped.
Adam wrote on :
Doesn’t seem to work anymore in Chrome 14. It just says “Uncaught ReferenceError: Invalid left-hand side in assignment” in the console. This works, however:
Tested and works in the latest WebKit/Gecko/Opera. Here’s the output from testing IE 5.5 to 10, Chrome 14 and iPad Safari 4.3.1 in Tutti.
Ad@m
Mathias wrote on :
Adam: What doesn’t work? I can’t reproduce any issues with the code in the blog post.
MaxArt wrote on :
JSLint is a disgrace for all the JavaScript code artists.
It just doesn’t understand the power of JavaScript’s syntax.
Paul’s solution is the kind that I usually adopt.