On a recent project I used Alexander Farkas' HTML5 Shiv and I noticed that when minified the script was 2.274 KB. This seemed pretty large to me for a concept that John Resig demonstrated in essentially two lines (I realize that this is highly oversimplified, because John's doesn't include a check for support or all of the new HTML5 elements). I dug into the html5shiv source. It was 248 sloc, which seemed like a lot of unnecessary code for such a simple task. I achieved a much simpler shiv in only 14 lines:
(function(document) {
var div = document.createElement('div'),
elements = 'article|aside|audio|canvas|details|figure|figcaption|footer|header|hgroup|nav|output|progress|section|summary|video'.split('|'),
i = 0,
length = elements.length;
div.innerHTML = '<header></header>';
if(div.childNodes.length != 1) {
for(; i < length; i++) {
document.createElement(elements[i]);
}
}
})(document);
Minified it's only ~270 bytes (that's an 88% savings from the size of the Farkas Shiv). When combined with appropriate CSS, it worked correctly in IE 6, 7, and 8.
article,aside,audio,canvas,figure,figcaption,footer,header,hgroup,nav,output,progress,section,video{display:block;}
It seems that the meat of the Farkas shiv does some magic with creating elements and checking for functions within a try/catch. Is this meat and filler necessary? Is my solution adequate enough or does the Farkas shiv account for something I haven't considered?
EDIT
The script now creates it own style tag with the proper declarations (and still is only 21 lines!):
(function(document) {
var div = document.createElement('div'),
elements = 'article,aside,audio,canvas,figure,figcaption,footer,header,hgroup,nav,output,progress,section,video',
elementArr = elements.split(','),
i = 0,
length = elementArr.length,
script, style;
div.innerHTML = '<header></header>';
if(div.childNodes.length != 1) {
for(; i < length; i++) {
document.createElement(elementArr[i]);
}
script = document.getElementsByTagName('script')[0];
style = document.createElement('style');
style.innerHTML = elements+'{display: none}';
script.parentNode.insertBefore(style, script)
}
})(document);