In this post I’ll be talking about the HTML5 and CSS3 feature polyfill library called Webshims Lib and how to use it correctly.
Polyfill?
In web development, we call scripts that emulate parts of the HTML5 or CSS3 specification “polyfills”. A polyfill can be nearly anything – a JavaScript library that adds support for CSS3 selectors to old versions Internet Explorer (i.e. Selectivizr) or a high end Flash based solution to enable the <audio>
and <video>
tag all the way back to IE 6 (i.e. html5media).
Introducing Webshims
The Webshims Lib is one of the most complete polyfills out there. It is based on jQuery and Modernizr. Including this one script will enable many features across the whole range of desktop browsers.
Webshims enables HTML5 and CSS3 features like semantic tags, canvas, web storage, geolocation, forms and multimedia. Reading through this big list, the first thing that might come to mind is how huge this library must be. Meaning a huge download size and long script execution time. But here is the kicker, Webshims will automatically detect which features the users browser supports and it only loads what is necessary to simulate everything else. This way it will not slow down users who already run a modern browser like Firefox or Chrome. You can even reduce the amount of features to load if you don’t need everything.
How to Use Webshims
To use the webshims lib you need to include the dependencies jQuery and Modernizr alongside Webshims Lib.
<script src="scripts/jquery-1.8.2.min.js"></script>
<script src="scripts/modernizr-custom.js"></script>
<script src="scripts/webshim/polyfiller.js"></script>
Now you need to initialize Webshims and, if needed, tell it which features you want to use.
<script>
// Polyfill all unsupported features
$.webshims.polyfill();
</script>
<script>
// Polyfill only form and canvas features
$.webshims.polyfill('forms canvas');
</script>
And that’s it! Webshims will automatically detect and polyfill missing features depending on the user’s browser. If you are curious the full feature list is:
- json-storage
- es5
- geolocation
- canvas
- forms
- forms-ext
- mediaelement
- track
- details
Example
Let’s do an example using the <video>
tag. First let’s create the basic page without Webshims or any other polyfill.
<!DOCTYPE html>
<html>
<head>
<title>Video native</title>
</head>
<body>
<video width="480" height="360" controls="controls">
<source src="Video.mp4" type="video/mp4">
<source src="Video.webm" type="video/webm">
</video>
</body>
</html>
Modern browsers will display this video correctly, but Internet Explorer 6, 7 or 8 will not.
Now we change the example to embed the Webshims Lib. You can see that it’s not necessary to edit anything else.
<!DOCTYPE html>
<html>
<head>
<title>Video including polyfill</title>
<script src="scripts/jquery-1.8.2.min.js"></script>
<script src="scripts/modernizr-custom.js"></script>
<script src="scripts/webshim/polyfiller.js"></script>
<script>
$.webshims.polyfill('mediaelement');
</script>
</head>
<body>
<video width="480" height="360" controls="controls">
<source src="Video.mp4" type="video/mp4">
<source src="Video.webm" type="video/webm">
</video>
</body>
</html>
The modern browser will display its native <video>
tag player but now this functionality is also available in Internet Explorer 6+. You can try the demo here.
Conclusion
As the example has shown, it’s really simple to use the Webshims Lib. There is no need to alter your code and it does not slow down users which use a modern browser. It enables everyone to enjoy all features your page provides. Head over to the Webshims homepage for the download, documentation and more demos.
This is a really cool and useful library. Thanks for sharing!
All the code is showing non-breaking space HTML entities. Makes is a bit hard to read!
Interesting! On one hand Christian Heilmann is talking about the vanilla web diet to simplify the web and on he other hand we have polyfills to support every other feature on all possible browsers available on the planet…
Finally a ‘one stop’ polyfill/script to go to to have IE work correctly. Good thing I’m subscribed to css-stricks.com :)
Two questions on your post though:
1- Why are your code examples displaying
and&
? If there’s a way you could fix this that’d be great so we don’t have to ‘exclude-scan’ the unnecessary markup.2- In your HTML structure you are now recommending adding the scripts in the
<head>
section. We all know this is not a recommended/best practice.However, I see that Webshims Lib is dependent on the loading of jQuery and Modernizr, but usually Modernizr does go in the
<head>
but jQuery goes as close to the closing</body>
tag as possible.Is the loading order of jQuery and Modernizr mandatory for this Webshims Lib to work?
I think is important you consider these issues when creating a “how to use it correctly” post like this one.
The readme.md section on Github of this script doesn’t help much either.
Thanks.
Oh well, never mind about question #1, seems you fixed that now. Thanks :)
loading order is obviously important (since webshims is built on top of jQuery), but I don’t see anything that implies it must be done in the <head>.
The github README states that you need to wait for the document to finish loading before using any of the polyfilled features (which is good advice anyway), but also implies that you don’t need to wait to call
$.webshims.polyfill()
.Given that, I’d suspect that it’s perfectly safe to put everything at the bottom of the page (or in an
onload
event in the <head>, which accomplishes the same basic goal).Thanks for the great explanation of polyfills.
However, I’m the video demo is not working for me in IE7 or IE8. Is it working for anyone else?
ps. I’m on a Mac using Virtualbox with the VMs that Microsoft provides for IE testing. Perhaps my setup isn’t a good test environment after all?
whoops. Meant to say, “However, the video demo…”.
real IE7 – nope
real IE8 – yup
IE7 = Nope
Win 7 using virtual box (vista)
Thursday must be the new Monday
loaded flash on the virtual machine as alexander farkas suggested below and video plays.
My bad
D’oh! That was my problem. Just needed to install Flash on my VMs. That’s why I love this site: Step 1: Flaunt my ignorance. Step 2: Learn stuff. Thanks.
May be a silly question but does this replace modernizr or go along with it? i.e. Do I need to include both scripts?
@D
No it’s an addition to Modernizr. Modernizr is the best feature detection script on earth. Webshims builds on top of this to do the polyfills.
@traq
demo works for me in real IE6/7/8 (obviously you need flash installed).
@Ricardo
Loading order is cruical, but you can of course add jquery + webshims to the bottom of your page. But in short, I don’t think that this is always a good/best practice. There is really a lot to say about this rule and it’s just a workaround. Actually I think it is often a bad practice to put JS at the bottom. If your JS is crucial for the UI and functionality of your page, you should load it (blocking) from the head, if it’s not that important you should load it async from your head (using either async attribute or a script loader) and if it’s just adding some little extras (lightbox) you can load it async + delayed (onload/domready) from your head. You should also consider, that this rule was established in an IE6/IE7 era. In this time adding a script at the top not only blocked UI rendering, but also forced sequential downloading. This has changed since then and webshims always loads the polyfills async. (Combining async loading + delayed loading, will increase FOUCs without giving you a big speed boost).
@Daniel
Many thanks for this post!
hmm.. what version of flash is required?
Well, I have to say I strongly disagree with several comments you mention. But I also have some questions since you mention several interesting things:
1.- “[…] add jquery + webshims to the bottom of your page. But in short, I don’t think that this is always a good/best practice. “ – Not sure why don’t consider loading scripts at the bottom a good practice, many people do it: HTML5boilerplate, 320 And Up, etc. to name a few. If Yahoo developers recommend it, with great justifications, not sure why you’re against that practice.
I personally do it and will keep doing it because it makes sense from a technical, performance and SEO points of views.
2.- “[…] it’s just a workaround” – A workaround for what? I may be missing something then, but I don’t see anything to workaround of by placing the scripts at the bottom.
3.- “If your JS is crucial for the UI and functionality of your page, you should load it (blocking) from the head” – With today’s JavaScript features at our fingertips and the learning curve brought so far down by jQuery, I’d say that most of everyone’s JavaScript is crucial for the UI and functionality of our pages. Webshims is a clear example of this.
Yet, I don’t see going back to loading all the scripts in the
<head>
section any better than that we already know as a best practice to load them at the bottom of the markup.4.-“[…] load it async from your head (using either async attribute or a script loader) […] load it async + delayed (onload/domready) “– Question: Haven’t heard of loading scripts ‘asynchronously’ or with a script loader or ‘delayed’, I’m not a JavaScript developer/guru. Can you provide any insight on this? Thanks in advance.
5.- “You should also consider, that this rule was established in an IE6/IE7 era.” – We are still in that era Alexander, the only difference is that we have more advanced browsers in the mix, but IE6 and IE7 are very much still with us.
In addition to this, Yahoo’s developers recommendation of placing scripts at the bottom of the markup has nothing to do with IE. So, not sure how your statement is justified.
6.- “In this time adding a script at the top not only blocked UI rendering, but also forced sequential downloading.” – You are correct in that adding scripts to the top (
<head>
) blocks UI rendering, hence, you are now starting to contradict yourself since you just said: “If your JS is crucial for the UI and functionality of your page, you should load it (blocking) from the head”.On the other hand, sequential downloading happens no matter where you put your JavaScripts, in the
<head>
or at the bottom of the markup. Unless I’m unaware of something regarding loading of JavaScripts.Not sure what “this time” means though. Sequential downloading has been here since this ‘machine’ was created.
7.- “This has changed since then and webshims always loads the polyfills async.” – What has changed “since then” if you just said “In this time…”. Another contradiction. It’s kind of hard to get your ideas…
8.- And one final contradiction: In your final statement you say that “(Combining async loading + delayed loading, will increase FOUCs without giving you a big speed boost)”, but above you actually just recommended doing it: “[…] you should load it async from your head (using either async attribute… […] you can load it async + delayed”.
As for the FOUC, I personally don’t see that as a huge deal. Yeah, it’s annoying, but that’s the nature of the beast and it’s just a matter of time before we don’t have to think about it anymore, just like we don’t think about
-moz-border-radius
anymore (unless you’re using a mixin that automatically includes it in your compiled CSS).My take-away from all this is simple:
A. There’s no justification to not keep placing JavaScripts at the bottom of the markup. Of course, correct loading/stacking order is mandatory, but still, placing them at the bottom is absolutely Ok and a still a best practice.
B. We are still in the IE6/IE7 era. Can’t wait for the day I (we) don’t have to consider those characters anymore :)
C. I have no idea what async loading nor delayed loading nor a script loader are or how they work. If you or anyone has any info on that that could share, that’d be great.
D. I wish I had this conversation in person since I never get to talk at this level with anyone, not even where I work, I’m sure there’s plenty of stuff I need to learn from you and your work.
I will be adding Webshims to my Web Design toolbox now :)
Thanks.
A. There’s no justification to not keep placing JavaScripts at the bottom of the markup. Of course, correct loading/stacking order is mandatory, but still, placing them at the bottom is absolutely Ok and a still a best practice.
There most certainly is. I’ve no idea what platforms and types of users you support, but 90% of the code I work on (which was not written by me) loads 95% of the Javascript in the head. So me, as a developer, if I need to concern myself with load orders, I too must load in the head or I will break things.
B. We are still in the IE6/IE7 era. Can’t wait for the day I (we) don’t have to consider those characters anymore :)
I feel bad for you. I really do. I haven’t had to worry about IE7 support in two years. IE8 issues only arise when a client specifically requests IE8 compatibility. You can’t wait for the day supporting Medieval browser ends? Then stop supporting them! By continuing to support them, you are supporting the problem. Many of us have already had that talk with bosses, clients, etc. I suggest you do the same and start giving them compelling reasons why old browsers are an incredible waste of time, resources, and ultimately, money. If they aren’t listening to you, you aren’t being compelling. If you intend to wait on enterprise users to switch to modern browsers, you will keep waiting for years.
C. I have no idea what async loading nor delayed loading nor a script loader are or how they work. If you or anyone has any info on that that could share, that’d be great.
There is plenty of info about async loading out there. I find it a bit smug that you begin to tell the author that his opinions are wrong when you yourself admit “I am not a Javascript guru”.
D. I wish I had this conversation in person since I never get to talk at this level with anyone, not even where I work, I’m sure there’s plenty of stuff I need to learn from you and your work.
This is not surprising.
But if understand it right then the polyfill gets also loaded in the browsers that do have native support for the HTML5 or CSS3 features you polyfill?
Or can, or even should, we load it with Modernizr.load yep/nope?
“Webshims will automatically detect and polyfill missing features depending on the user’s browser.”
Sorry… I should have read better, before I asked my question.
This video played for me in IE 6 – 8. Impressive!
@Ricardo
If other people jump off a cliff, do you jump after them as well? “But other people are doing it as well” is hardly ever a valid argument.
Yahoo’s developers made this particular recommendation in a time when asynchronous script loaders did not exist, resources were still requested asychronously, the average web server and web proxy did not set proper far future expiration cache headers, etc.
We have a name for blindly following these kind of recommendations without periodic re-evaluation of their validity; it’s called cargo cult programming.
RequireJS would be something nice to read and learn about. It’s a script loader that uses the emerging Asynchronous Module Definition (AMD) spec from CommonJS.
No offense, but for the < 2% browser share I commonly see, I wouldn’t bother adhering to old cargo cult practices to optimize speed for gimped, underpowered browsers that are more than likely running on outdated hardware and are rapidly approaching a final death.
You are unaware of that fact that IE8+ and any contemporary version of the other major browsers download scripts in parallel. Only execution still happens sequentially (and you can even turn that off…)
OFFTOPIC–
The “cliff” analogy, lol. I’m sure I’m quite old for that one :p
I “ain’t” jumping off just FFOI, actually I’m not jumping at all, and if I would be jumping, I would be jumping with many of the ‘big boys’.
Cargo cult programming, got it, makes total sense: I’m not a programmer. Interesting nonetheless.
Yes, Require.js, I’ve read a lot about it but haven’t really understood some of the concepts of it, now I have a better idea of what that is.
No offense taken Ron, you and I are in the same boat and share the same view. However, the share I commonly see is way, way higher than yours. I do have to say that I don’t do anything for IE6 anymore and certainly push as hard as I can to minimize IE7 extra-work.
I don’t think IE6/IE7 are approaching a rapid death, au contraire mon ami, we’ve all experienced their immensely slow one.
Yes, I was unaware about modern browsers downloading scripts in parallel. I recently learned a quite a bit about this parallel-sequential downloading regarding CSS when using
@import
vs.link
, but nothing about parallel-sequential download for scripts was discussed.Now I know.
Thanks for the info, very helpful.
Derp; that should read; “were still requested synchronously.
I only have IE9 (not my normal browser), and when running in Browser Mode: IE7/8/9 Compatibility, it wasn’t working…
But then I checked and found Flash was not installed for IE… :-)
Installed, and working like a charm, great find!
Atg
@Ricardo Zea /offtopic
About async and normal loading behavior of JS. Normally browsers can load 2-8 files simultaneously per domain (old browsers like IE6/7 or FF3.0 do 2 others 4-8). And loading files parallel is obviously much faster than sequential.
The reason behind the rule “Put your JS at the bottom” is the following:
As soon as you normally add a script[src] to your HTML, it will block your browser from doing the following tasks:
a) Download other resources (only true for IE6/IE7, IE8 started to change this and IE9 and other browsers are extrem good here)
b) parse HTML into DOM (only true for IE6/IE7)
c) render UI (all browsers)
So putting JS at the bottom minimized the problem, because there is no other download resource, which can be blocked and the DOM + UI is parsed/rendered to 99%.
This rule was established at a time, where all browsers blocked everything. As you can see a) and b) is only true for IE6/IE7 and only point c) is there in all browsers (and won’t change, because this is the way how browsers work). Actually not blocking the UI rendering always means, please create a FOUC. This is really important to understand. FOUCs are not a side effects of the rule “Put JS at the bottom”, they are intended. Because you as a developer say with this: My JS is not important for the UI, please do the JS stuff at the end.
async loading of scripts is a really nice technique to avoid problems of a, b and c in all browsers (even in IE6/7), while you have better control over the FOUC problem. The point here: As soon as you are using async loading, nothing is blocked, but due to the fact, that you can start your script download already in the head element, the script can be downloaded, parsed and executed much earlier and if it is inside the clients cache, you won’t produce a FOUC/FOUBC.
With delayed loading, I simply mean, that you can delay the async loading of a script (after a timeout, after domready or after onload), if this script is not important for your UI (for example lightbox), this technique might be helpfull, because although you are using non-blocking script loading techniques, loading a script consumes 1 http request, which could be used for a content image for example.
The only problem with async loading is the fact that the execution of your scripts aren’t ordered anymore and this can create race conditions. Webshims loads all async (without any blocking) and handles the race condition problem very efficiently (similiar to requirejs).
Great explanation Alexander, thanks a million.
Not sure how I missed Chris’ Thinking Async post, will read it as soon as I post this reply.
Now, with yours and Ron’s explanations above, I’m sure I’m not the only one re-evaluating where/how to place the scripts in my markup since now I have new information and reasons to reconsider. Hmm… this sounds like I may be jumping off a cliff with you both, lol.
I’m sure no programmer where I work has any clue about anything we’ve discussed here regarding browsers, asynchronously and delayed loading of scripts, so I’ll be sure to let them know a few new things now.
Again, thanks for all the info, very helpful.
@traq
Flash needs version 9.0.115 to play h.264 videos.
Can Webshims be used with HeadJS instead of Modernizr?
Not at the moment. It’s dependent on both Modernizr & jQuery libraries.
Can this be used to enable SVG as well?
Hot Drama!!!! I hope @ChrisCoyier will post a SceenCast soon on , where and when to load them.
Will this work with jQuery 2.0 + once it doesn’t support old IE versions?
seriously Chris, you lost me on this one, more than one thing i can’t figure out.
Useful code and very interesting, I think I need coding touch also to understand this.
Well…. it fixed a problem where safari doesn’t support html5 validation(twitter bootstrap).
And I guess IE8 will just always be IE8. Never liked anything about Microsoft anyway.
Thanks for the tutorial.
Thanks for great explanation.
Just curious know can we use yesNope.js to embed the our own polyfill for the feature don’t not exist in webshim lib. Else the any other way to embed just by using webshim itself. Or if I use yesNope.js how about performance.
Thanks in advance.