7

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);
Bailey Parker
  • 15,599
  • 5
  • 53
  • 91
  • 6
    Personally, I think downloading all that extra code is a suitable punishment for someone running IE6/7/8. In fact, perhaps we should add a few meg extra, just to make sure. – SDC Aug 23 '12 at 13:01
  • @SDC Right on! I probably already have a meg of IE specific CSS. Does that count? :P Your comment reminds me that I neglected to account for the fact that an `IE lt 9` user would probably have the shiv in their cache already. But my question is more about code bloat than download times. – Bailey Parker Aug 23 '12 at 13:11
  • Hopefully my real answer below goes some way toward answering the question :-) – SDC Aug 23 '12 at 13:13

1 Answers1

4

The main difference between your code and html5_shiv is that your version only caters for IE's lack of support for the HTML5 elements during the initial loading of the page.

There are, in fact, significant further issues to be dealt with, which you will encounter if you use Javascript to modify the page content after loading.

At one point, there was actually a secondary script called html5 inner shiv, which solved these problems. However, more recent versions of the main html_shiv script have incorporated these fixes as well, so the secondary script is no longer required. But it does mean that the main script is now a lot bigger.

This accounts for the amount of code you've seen.

If your HTML is going to be static, then the answer is no, you don't need all that extra code; your version is fine. (or you could go to the html5_shiv Github page and download a previous release; the early versions looked a lot more like your code).

But if you intend to write a site with any kind of dynamic content, then you would be well advised to use the full current version of html5_shiv. It fixes more than just the one issue.

SDC
  • 14,192
  • 2
  • 35
  • 48
  • +1 for the inner shiv. I should've known that when the shiv was messing with redefining `createElement` they were future proofing the shiv. However, I wonder why do you need the inner shiv (or the most recent version of the main shiv). Once you have created each of the HTML5 elements once with js, won't the browser be aware of them for the lifetime of the page? – Bailey Parker Aug 23 '12 at 13:17
  • The inner shiv page I linked explains the problem more clearly (if you can read it past the big "don't use this any more" message), but for now suffice to say that no, just creating the element isn't sufficient to fix all of the IE's deficiencies with handling unknown elements. – SDC Aug 23 '12 at 13:28
  • So this only fixes `innerHTML`. If you create all your elements (including the HTML5 ones) with `createElement` like you should, there is no need for this, right? – Bailey Parker Aug 23 '12 at 13:31
  • I believe it also has fixes for printing as well. Possibly more, but I think that covers the bulk of it. – SDC Aug 23 '12 at 13:49
  • 1
    Just to sum things up: As long as you don't use `innerHTML` to add HTML5 elements and you're not printing, the Farkas shiv can be simplified to my version. Agreed? – Bailey Parker Aug 23 '12 at 13:53
  • Well that's summed up enough for me. Thanks for the insight! – Bailey Parker Aug 24 '12 at 13:41