How Polyfills “fill in the gaps” to make HTML5 and CSS3 Usable Today

There’s been a lot of commotion over the last week since the W3C announced that HTML5 is not ready yet for deployment to websites. Some really smart people have weighed in on this topic and I agree with their thoughts. Last Thursday, I did a presentation on the new features of HTML5 and part of that was demonstrating how polyfills work to allow you to leverage these new features while still providing a good cross-browser experience.

What’s a Polyfill?

I really love Paul Irish’s definition since it sums it up perfectly:

polyfill: A shim that mimics a future API, providing fallback functionality to older browsers.

The basic premise is that most older browsers may not have all of the features of the HTML5 and CSS3 specifications and they need a helping hand to make them provide a good user experience. A great example of this are the new HTML5 semantic tags like <article>, <section>, <header> & <nav> which render fine in all major modern browsers like IE9 beta, Firefox, Chrome, Safari & Opera but lack support in popular browsers like IE6 through IE8.

So for my demo, I decided to create a simple page that showed a blog-like layout using these new tags while ensuring that they can still render correctly in IE8. Here’s the layout code I used.

[code lang=”html”]
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Rey’s Awesome HTML5 Blog</title>
<meta name="description" content="" />
<meta name="keywords" content="" />
<meta name="author" content="" />
<meta name="viewport" content="width=device-width; initial-scale=1.0" />

<!– !CSS –>
<link href="css/html5reset.css" rel="stylesheet" />
<link href="css/style.css" rel="stylesheet" />

</head>

<body>

<header>
<h1>Rey’s Awesome HTML5 Blog</h1>
</header>

<nav>
<ul>
<li><a href="#">Home</a></li>
<li><a href="#">About</a></li>
<li><a href="#">Contact</a></li>
</ul>
</nav>

<section>

<header>
<h1>Rey’s Blog Posts</h1>
</header>

<article>
<header><h1>The In’s & Out’s of HTML5</h1></header>
<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Fusce vitae orci. </p>

<footer>
October 7, 2010 – comments( 0 )
</footer>
</article>

<article>
<header><h1>HTML5 Ate My Lunch</h1></header>
<p>Fusce vitae orci. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. </p>
<footer>
October 5, 2010 – comments( 3 )
</footer>
</article>

</section>

<footer>
<p>Copyright Rey Bango, 2010</p>
</footer>

</body>
</html>
[/code]

I used a HTML5 reset style sheet because unfortunately, most browser don’t have an internal style sheet that sets the expected behavior for specific elements. For example, you would expect an <section> element to be block level but due to a lack of the internal browser style sheet, it renders inline.

Then, I added the styles I needed to get my page to look the way I wanted:

[code lang=”css”]
/* Global */
body { font-size: 16px; font-family: arial,helvetica,clean,sans-serif; }
a { color : #33CC33; }
a:hover { text-decoration: none; }

/* Header */
header h1 { font-size: 48px; }

nav { overflow: auto; margin-bottom: 25px; }
nav li {float:left; padding-right: 5px; }

/* Main Content Area */
section { width: 500px; font-size: 12px; }
section h1 { font-size: 16px; }

article { background: #CCCC99; margin-bottom: 10px; padding: 5px; -moz-border-radius:10px; -webkit-border-radius:10px; border-radius:10px; }
article footer { text-align: right; margin-right:5px; }
article h1 { font-size: 12px; }
[/code]

and when I tested it in Firefox 3.6.10, it looked exactly like I expected:

but look what happened when I tried to bring up the page in IE8:

None of the stylings were available because IE8 doesn’t recognize the new HTML5 elements. Further, in order to get IE6-8 to recognize these elements, you explicitly have to create the DOM nodes for them using JavaScript. The exact reason is unclear but it may be some type of parser bug. The following code needs to be in the <head> section of your page in order for the elements to be created and recognized by IE6-8:

[code lang=”js”]
document.createElement("header");
document.createElement("nav");
document.createElement("section");
document.createElement("article");
document.createElement("footer");
[/code]

It’s a little bothersome to do that but it’s not a massive bit of code at least.

Enter Modernizr

The code I just listed to create your HTML5 elements is certainly useful but work has already been done to handle that for us via the awesome Modernizr JavaScript library. Not only does it act as a polyfill, creating these new elements for us automatically, but it offers a ton of detection capabilities for features of both HTML5 & CSS3. This allows you to determine how you will offer fallback support when a feature isn’t available.

Including Modernizr.js is incredibly easy since it’s only a one line script tag like this:

[code language=”lang="html”]
<script src="js/modernizr-1.5.min.js"></script>
[/code]

As I mentioned, Modernizr is smart enough to determine when new semantic elements need to be created and will handle the dynamic creation of elements such as <article>, <section>, <header> & <nav> instead of you having to write JavaScript code to do it. So once I’ve added Modernizr to my page, I get the following results in IE8:

Now you’re probably looking at this screenshot and say, “Hey, you have no rounded corners!”. You’re right because I used the CSS3 border-radius property to create rounder corners for all of my <article> elements and IE8 doesn’t support that property. The important thing, though, is that IE8 now recognizes these new elements and allowed me to style them.

But What About those Rounder Corners?

Geez, you guys are so demanding! Okay, so the cool thing is that Modernizr offers detection of key features of HTML5 *and* CSS3 and with that, we can determine if something like border-radius is available and if not, using a new term coined by Alex Sexton, we’ll use “regressive enhancement” to provide similar capabilities for older browsers. In this case, we’re going to see if border-radius is available and if not, lazyload in Mike Aslup’s jQuery Corners plugin to fill in the gap:

[code lang=”js”]
<!– Load jQuery –>
<script src="http://ajax.microsoft.com/ajax/jquery/jquery-1.4.2.min.js" type="text/javascript"></script>

<script type="text/javascript">
// See if border-radius is available
if (!Modernizr.borderradius) {

// If not, then load in the jQuery Corners plugin and apply rounded corners to the article elements
$.getScript("js/jquery.corner.js", function () {
$("article").corner();
});

}
</script>

[/code]

Now, when the code detects that border-radius is not available, it will just use the Corners jQuery plugin instead and render the following in any browser that doesn’t support the property:

Download the Code

I hope this post has shown you how polyfills can allow you to use HTML5 & CSS3 today. While I respect the W3C’s desire to ensure that the HTML5 specification is up-to-snuff, I think it’s important to realize that developers are resourceful and professional enough to create best practices that allow us to build apps with these new features right now.

I would highly recommend reviewing this VERY BIG LIST of polyfills and shims which can provide much of the missing capabilities in older browsers.

If you’d like to play with the code directly, I’ve packaged it up in a .zip file and you can download it here:

Code for HTML5 Semantic Tags using Polyfill to Degrade Gracefully (.zip)

Rey Bango

12 Comments

  1. Rey,
    Absolutely great post about doing this and ho to get it to work! I’m going to give this a try with the work I’m doing for the Intranet apps I’m building.
    Thanks,
    Doug

  2. I’ve been achieving similar results using HTML5 Shiv – http://code.google.com/p/html5shiv/ and Progressive IE (PIE) – http://css3pie.com/. Couple those with SASS/Compass CSS3 mixins and you’ve got a VERY CLEAN and a as-close-as-you-can-get-to-bulletproof method for making your sites backwards compatible with IE. Kinda mind-blowing to see CSS3 styling in an IE6 browser ;)

    • LOL. Well it’s actually a reference to the Ajaxian frontpage by someone that leached an article I wrote for that blog. ;)

  3. I can’t bring myself to rely on Javascript to get IE to work for something as essential as the actual tags and structure of the entire site, nevertheless one that would be browsed by near 50%+ of the population!

    HTML5 is cool, but WC3 was right. It’s simply just not ready yet. Besides, I’m having more than enough fun just playing with CSS3 that easily degrades. I’ve waited this long for semantic structure, a little longer won’t kill me.

  4. Nice article.

    I still have a bit of an issue with these Javascript based solutions: what happens when Javascript isn’t available?

    The other problem with JS solutions is the noticeable time it takes to load and run, often resulting in unsightly flashes of broken / unstyled content. If developers start loading jquery plugins to fill each gap in IE’s CSS spec, their site’s loadspeeds are going to slow down drastically.

  5. This article covers a great deal of information for the guys who want to leverage html5 features but are reluctant to try as IE 6 – 8 comes into picture. I am just wondering if there is polufill available for each and every html5/css3 feature. say I want to leverage css3 properties like box shadow, text shadow or say html5 video, audio tags. Is there certainly a polyfill available for all of those.

Comments are closed.