Building Applications with HTML5
Adoption Strategy for HTML5: Leaving No Browser Behind Click the link to download the sample code HTML5 comes with many exciting features. With new tags, new CSS powers, and new JavaScript APIs, the capabilities of the web have taken a huge leap. In addition to the soaring morale among browser vendors, the list of exciting new features is growing almost daily. From nightly builds to development channel releases and standard platform previews, browsers are evolving rapidly, and web developers around the world are joining in on the celebration.
However, despite the developer and browser community pushing the hype around HTML5 to an extreme high, most people online are not using the latest browsers and versions like we do. If you are a web developer at a large development agency or part of a big company with a large user base, you may be quite aware of this. Even working for a small agency or a startup that provides services via the web, you might find yourself spending a lot of time ensuring your site can support as many browsers and browser versions as possible.
Given this reality, it is easy to see that HTML5 is not about whether it is ready for today’s use but whether you are ready for it. For instance, suppose you’ve created a new page with some new semantic tags (like
Before you decide to wait until 2022 to consider HTML5, I suggest you continue reading the rest of this article, where I will provide you with some practical strategies that you can adopt HTML5 technologies now while avoiding the poor degradation shown in Figure 2. I will cover the following three topics in detail:
These should teach you a lot about what you need to know about building a website that works across various browsers. By the end of this article, you will have a reliable strategy that allows you to adopt HTML5 technologies confidently and without hesitation. You will also have some tools at hand that can progressively enhance your site for new browsers while still accommodating older ones.
The Importance of Feature Detection
To provide a stable and consistent experience across browsers, developers often need to get some information about the user’s browser. Previously, the common practice was to use JavaScript to sniff this information as follows:
var userAgent = navigator.userAgent;
if (userAgent.indexOf('MSIE') >= 0) { console.log("Hello, IE user"); } else if (userAgent.indexOf('Firefox') >= 0) { console.log("Hello, Firefox user"); } else if (userAgent.indexOf('Chrome') >= 0) { console.log("Hello, Chrome user"); } This technique is called User Agent (UA) sniffing, widely used to determine which browser is requesting a page. The idea here is that knowing the user’s browser (e.g., IE7) can help decide what functionality to enable or disable at runtime. UA sniffing equates to asking the browser, ‘Who are you?’ (For an in-depth analysis of UA sniffing and other detection techniques, see bit.ly/mlgHHY.) The problem with this approach is that browsers can lie. The UA string is configurable information, and does not provide 100% accurate browser information. Moreover, with widespread adoption of this technique, many browser vendors have added extra content in their UA strings to fool scripts into making incorrect judgments about the actual browser in use, thereby avoiding detection. Some browsers now even provide tools that allow users to tweak the UA string with just a few clicks. The goal of UA sniffing has never been to determine the user’s browser and version. Nor is it definitely not to allow you to tell users ‘please download another browser’ when they are using a browser you don’t like — even if some people use UA sniffing technology that way. Users have the right to choose which browser they use, and the developer's duty is to provide the most reliable and consistent experience without imposing browser preferences on users. The aim of UA sniffing is to give you a clear understanding of the capabilities or features available in the user’s current browser. Understanding the browser itself is just one way to obtain this information.
Currently, there are several alternatives to UA sniffing, one increasingly popular technique is called object detection or feature detection. These two terms can often be used interchangeably, but this article will use the term ‘feature detection’ uniformly. The goal of feature detection is to check whether a feature or capability is supported in the user’s current browser. If UA sniffing is asking the browser, ‘Who are you?’ then ‘feature detection’ is asking the browser, ‘What can you do?’ This question is more straightforward, and for providing features conditionally to users, this approach is also more reliable. When implemented correctly, a feature detection script makes it difficult for users or browsers to lie about or misreport feature support.
Manual Feature Detection
So, what does feature detection look like compared to the UA sniffing example? To answer that, let’s first look at how to resolve the issues when viewing the previous HTML5 page in IE8.
My Awesome SiteMy Awesome SiteAn Article Isn't this awesome?
There’s a significant visual difference between IE9 and IE8. For a beginner, my page has no styles at all because there’s no CSS for this page. Additionally, the playful HTML5 shield is missing from the bottom of the page. Each issue can easily be resolved, and feature detection is the first step to identifying problems.
The causes of both problems are simple: for IE8,
!!document.createElement('canvas').getContext
This line does several things. First, it uses two negation (!!) operators to coerce an undefined value explicitly to false. Then, it manually creates a canvas element and adds it to the DOM. Finally, it calls the getContext function, which is the most basic form of feature detection. Using this statement and similar ones provides a more reliable way to query the features supported by the browser. For more information on manual feature detection, see diveintohtml5.info/everything.html.
Using Modernizr for Feature Detection
Manual feature detection certainly improves over UA sniffing, but it still requires you to do a lot of work to check whether features are available and decide what to do when they are not. While the Canvas example is simple with just one line of code, not every feature you want to check will be that simple — detection code can vary across different browsers. For example, detecting support for the CSS3 modules used earlier (border-radius and box-shadow) can be a little tricky.
Fortunately, Modernizr (modernizr.com) offers a better way. Modernizr is a JavaScript library that “... detects whether a native implementation of the next generation web technologies (the features that derive from HTML5 and the CSS3 specifications) is available.” Adding a reference to Modernizr on your page provides the following four features:
A script loader that conditionally loads polyfills into the page.
This article will not delve deeper into the first item, but I encourage you to visit modernizr.com to learn about this feature and its documentation. For the second item above, you can change the following code:
!!document.createElement('canvas').getContext
to this line of code:
Modernizr.canvas
This line of code returns a boolean indicating if the page supports the Canvas element. The benefit of using Modernizr over doing feature detection yourself is that Modernizr is a well-tested, robust, widely adopted library that has done a lot of heavy lifting for you. Twitter, Google, Microsoft, and countless other organizations and developers are using Modernizr, and you can too. In the ASP.NET MVC 3 Toolkit update (released April 2011), Microsoft even bundled Modernizr with new ASP.NET MVC applications. Of course, what we have done so far is merely check if support for
if (Modernizr.canvas) { // Execute canvas code here. }
Add features to your site based on the additional browser capabilities, a practice called “progressive enhancement,” as the experience enhancement targets browsers with better capabilities. The opposite is “graceful degradation,” where the absence of a feature should not break or cause failure in the browser; rather, it should provide users with a diminished functionality or alternative capability. For older browsers, graceful degradation should not be assumed as the default option. In many cases, it may not even be the best choice. Instead, with the help of Modernizr, you can typically use several available browser polyfills to bring HTML5-like functionalities to browsers that do not support HTML5.
What is a Polyfill?
According to the Modernizr website, a polyfill is “a JavaScript supplement that replicates standard APIs on older browsers.” “Standard APIs” refer to HTML5 technologies or features, like Canvas. “JavaScript supplements” refer to the additional JavaScript code or libraries that are dynamically loaded to simulate these standard APIs in browsers that do not support them. For example, a geolocation polyfill can add a global geolocation object on the navigator object, as well as the getCurrentPosition function and the ‘coords’ callback object, all of which are defined by the W3C Geolocation API. Because polyfills mimic standard APIs, they enable development towards these APIs in a way that considers all browsers’ futures, with the ultimate goal being: once support for these APIs reaches a substantial majority, the polyfills can be easily removed without any extra work.
By adding a reference to Modernizr on the page, I received the direct benefit of polyfills related to this example. The page displayed without styles because IE8 does not recognize
Besides adding support for new HTML5 elements in IE, the Modernizr library does not by default provide any other polyfills. Additional polyfills can be provided yourself or chosen from the growing list of options available on the Modernizr website. In version 2.0, Modernizr provides a conditional script loader (based on yepnope.js — yepnopejs.com) that can help you load polyfill libraries asynchronously only when needed. Using Modernizr alongside one or more polyfill libraries to provide the required functionality is a powerful combination.
Using Polyfills to Simulate HTML5 Capabilities
For Canvas, with the help of Modernizr and the JavaScript library excanvas, using a polyfill can implement Canvas support in IE8 and earlier versions, adding API-level Canvas support to IE6, IE7, and IE8. You can download excanvas from bit.ly/bSgyNR, put it in your scripts folder, and then add some code to your page’s script block.
Implementing Canvas Support with Modernizr and Polyfill
Modernizr.load({
test: Modernizr.canvas, nope: '../js/excanvas.js', complete: function () { Modernizr.load('../js/html5CanvasLogo.js'); } });
Here, I specified three things using the Modernizr loader:
The callback that runs when the check or script loading is complete.
For Canvas, this smart handling and polyfill is all I need to add in the application. Modernizr will asynchronously load excanvas.js, and it will only load for those browsers that do not support Canvas, then load the script library to draw the HTML5 logo on the page.
Next, let’s look at another example to understand the value of Modernizr. Noticing details, you may have observed that the styles of the website in Figure 4 match those of the original page shown in Figure 1 in IE9. This page shows without shadows and rounded corners in IE8, and I can’t deliver the site ugly without those two effects, so we turn to Modernizr once again.
Just like handling Canvas, Modernizr can tell me that CSS modules are not supported but offer a library to fill in (polyfill) these CSS modules for me to use. Fortunately, there’s a library called PIE (css3pie.com) that provides both modules in one library.
To add support for rounded corners and shadows, after downloading PIE, I can add the code from Figure 6 in my script. This time, I will check whether the border-radius or box-shadow module is supported (instead of assuming either are supported or not) and if any of those modules don’t support, load PIE.js dynamically. After PIE loads complete, I will execute some jQuery code that selects all
Modernizr.load({ test: Modernizr.borderradius || Modernizr.boxshadow, nope: '../js/PIE.js', callback: function () { $('article').each(function () { PIE.attach(this); }); } });
Using Polyfills to Assist with Graceful Degradation
In addition to the polyfill techniques discussed here, Modernizr can also help when you want your application to degrade gracefully, rather than using another library for polyfilling.
Suppose there’s a Bing Maps control on the web page, and I want to use Geolocation (which I will go into depth in future articles) to determine the user’s current location, then drop a pin on that location in the map control.
While newer versions of browsers support Geolocation, older browsers do not. Providing complete Geolocation support using pure JavaScript can be quite cumbersome, and even with a Geolocation polyfill, it’s not easy. Therefore, I decided to gracefully degrade my application. When the user’s browser does not support Geolocation, I will provide a form where the user can manually input their location, and I will position and pin the map using the user-provided location.
Using Modernizr, I can simply load one of the two scripts I created with a simple loader script, as shown in Figure 8. In this example, I am testing the Modernizr.geolocation property. If it’s true (the ‘yep’ branch), I will load the fullGeolocation.js script, which uses the Geolocation API to locate (to get user permission) and place the location on the map, as shown in Figure 9. If the test is false (the ‘nope’ branch), I will load a fallback script that shows an address input form on the page. When the user submits the form, I will center and pin the map using the address provided by the user, as shown in Figure 10. This way, my page offers a great experience for the latest browsers while gracefully providing a reasonable alternative for older browsers.
Modernizr.load({
test: Modernizr.geolocation, yep: '../js/fullGeolocation.js', nope: '../js/geolocationFallback.js' });
When faced with a massive user base still using old browsers, it's easy to think that some of HTML5's advanced features are not applicable to your site. However, there are now excellent solutions available that not only help you gracefully degrade but also enhance the capabilities of older browsers, allowing your users to experience HTML5 capabilities right away. In this article, you have seen feature detection, Modernizr, and polyfill technologies, so you can confidently adopt HTML5, pleasing both the growing user base of those using the latest browsers and not losing your substantial user base using older browsers. The above content is sourced from: http://msdn.microsoft.com/en-us/magazine/hh394148.aspx