Official website for Web Designer - defining the internet through beautiful design
FOLLOW US ON:
Author: Steve Jenkins
22nd August 2013

Get total browser support with this Modernizr masterclass

Achieve all browser support with the this comprehensive guide to the feature detection library Modernizr

Get total browser support with this Modernizr masterclass
The modern web is a wonderful thing. The arrival of HTML5, CSS3 and mature JavaScript frameworks such as jQuery has completely transformed the landscape of web design, which allows designers to create advanced interactivity and craft beautiful layouts with ultimate ease. We have never had it so good!
Unfortunately, while this utopian view is certainly based in truth, we can’t ignore the past. For practising web designers, there’s a daily consideration that presents challenges and frustrations alike: the out-of-date browser.

The problem with older web browsers is that they don’t necessarily support all those fancy new features that you’re desperate to use. They might not understand some of the CSS you plug in to your stylesheet, but happily deal with other, older properties. It can quickly become frustrating working to support these less-capable browsers, and it can be tempting to fall back to the lowest common denominator.
By avoiding the latest features of CSS3, and sticking with tried-and-tested XHTML tags, all the problems of testing and providing workarounds can be avoided – right?

One of the biggest challenges with adopting new practices and tools is knowing which browser supports which features. When we only had to contend with a couple of versions of Internet Explorer, and the first version of Firefox, it was straightforward; we knew what each browser was capable of. This allowed designers to target the behaviour and capabilities of the two, optimising a design to suit each different one.

These days, however, there are at least half a dozen perfectly viable and capable browser options for web users to choose from, and each has several versions in the wild at any one time. It’s become almost impossible to be intimately familiar with the individual support characteristics of each web browser that might be used to access your website. As a result, it’s no longer practical to target individual browser versions. Thankfully, there’s a simple and elegant solution….

What is Modernizr?

Modernizr is a JavaScript library that allows you to use feature detection to determine whether the browser being used to access your website is going to be able to render specific types of content, or will support particular features. The library works by allowing you to check for support within the browser against a series of tests. For example, if you’re using CSS transitions, you can test for the browser’s ability to render these and, if the browser doesn’t handle animations, provide a fallback or alternative.
Put in simple terms, Modernizr allows you to write conditional CSS and JavaScript to tailor the experience of your website according to the capabilities of the user’s web browser.

The library is quick to install, and simple to use. When a page with Modernizr loads, a JavaScript object is created that contains the results of the tests. CSS classes are added to the <html> element, allowing you to check either via script or CSS whether a specific feature is supported.
You may be wondering what tests can be run, and which features are supported by Modernizr. What makes the library so useful is that it’s almost a one-stop shop for browser functionality-support testing. Modernizr allows you test for over 40 next-generation features including font-face, rgba, CSS animations, gradients, canvas, HTML5 audio and video, local storage and WebGL. You’re not tied into running tests for every single feature, however. A great strength of Modernizr in particular is its modular nature; you only need test for the features you need, rather than having to conduct every individual feature.

Get total browser support with this Modernizr masterclass

Why use it?

The benefits of using Modernizr as opposed to the more traditional approach of sniffing for a particular browser and operating system are vast and numerous. The feature-detection approach is more reliable by far, it isn’t tied to specific browsers and takes account of individual users manually overriding their browser’s user agent property.

Modernizr makes it simple to build a set of functionality and polyfills once. You can then rest safely in the knowledge that as browsers are updated and new functionality is introduced, your website design will continue to work as expected.

It’s also a much more convenient method of providing a fallback for less-capable browsers. The library executes in milliseconds, providing access to all the hooks you need to identify feature-deprived browsers. Plus giving you a single framework to use for all your polyfill (where you replicate functionality using alternative solutions) requirements.

Most importantly of all though, Modernizr allows you to use cutting-edge HTML5 and CSS3 features to progressively enhance your designs, without excluding older browsers. You can use the library to selectively enhance the user experience for modern browsers by employing the script loader, allowing you to provide a basic consistent experience for all browsers, then add bells and whistles safely.

A further benefit of Modernizr is that you can tailor the library in a modular fashion so that you’re only downloading the code necessary for the specific tests you require. If you’re happy to accept the overhead associated with all 40+ tests, you can still get performance enhancements by using a Content Delivery Network (CDN) hosted version of the library. This latter option allows the user’s browser to cache its first download of the library, and then call upon the cached version on all other sites that use the same Content Delivery Network.

However, the slimmest and best solution is to tailor the library to the specific tests you need to run on your website. If you only need to test for support of geolocation, or only want to know if you’ll be able to load external fonts successfully, the custom builder allows you to exclude all other tests, and any unnecessary utility methods, making the download (and overhead) tiny.

The benefits of using Modernizr

We’ve already touched on how Modernizr is superior to the more traditional method of browser sniffing, using navigator.userAgent. While this method worked at the time, the premise was based on a limited number of browsers and sketchy support for features, to the extent that it was necessary to target individual browsers in order to achieve a consistent look between them.

Whereas in the past it was extremely common to use CSS hacks, we’re now in a more enlightened age where we’re happy to accept that not every browser will render a page identically. However, we do still have the problem of different browsers offering differing levels of support for features.
There are numerous ways of dealing with the issue, but Modernizr offers the cleanest solution to feature-detection, and allows you to embrace the most cutting-edge features within HTML5 and CSS3, all without compromising the user experience for older web browsers.

As well as the ease of developing according to supported features, there’s a further benefit that might not be immediately apparent.As websites have become more complex collections of rich media and user interactivity, so the weight of page downloads has increased. It’s not uncommon for one page to require as many as a hundred files to be downloaded. This is especially true where the designer has provided workaround solutions or polyfills for older browsers. Frustratingly in the case of workarounds, not all browsers actually need the workaround code – only those that don’t support the given feature.

Modernizr allows you to circumnavigate this issue, but acting as a loader for stylesheets and scripts, according to the result of the test(s) conducted. This is made easier by the integration of yepnope.js, which is a library designed to allow for conditional resource loading. YepNope actually adds some additional features that can further improve performance, including the ability to prevent the same script being executed twice.

As well as feature-detection and conditional resource loading, there are other reasons to use Modernizr. If you’ve ever used HTML5shiv/shim you’ll be familiar with the idea that older browsers, especially in the Internet Explorer family, don’t support the newer HTML5 tags such as <article>, <section>, <header> and <nav>. The shiv adds support and sets these new tags to behave akin to a <div> tag.

Modernizr has an optional HTML5 shiv built-in, and this can be enabled from the Extra section of the production-library configuration tool. By including the shiv within Modernizr, you’re automatically fixing older browsers at the same time as conducting tests for features. That’s not to say that browsers that don’t support <audio> will suddenly be able to play audio files, but it provides a fail-safe way to use the latest semantic HTML5 tags without having to worry about older browsers.

Setting up the library is very quick and easy to do. And what’s more, by customising the features that you’re testing for, you can limit the weight of the script to a minimum. This makes it a really effective way to handle and cater for browser differences without adding bloat.

How to setup Modernizr

1. Configure and download
Take a visit to the Modernizr website at http://modernizr.com and click on the Download menu option. If you want to run every test, you can take a shortcut and click on the download button for the Development version, which includes the kitchen sink. If you’re creating a production-ready version, however, the configuration utility allows you to choose specific features to test for.

2. Add the script
Now that you’ve got your version of Modernizr, either as a development version or a custom-build, you need to add it to your page source code. Use a set of standard <script> tags to add the library, making sure you do inside the <head> section of the page. This will ensure the library runs as early as possible when the page is loading.

001    <script type=”text/javascript” href=”/    scripts/modernizr.js”></script>

3. Use the library
The quickest way to make use of the library is to target specific styles using the handy classes appended to the HTML element. This allows you to restrict particular CSS code to browsers that support specific features. If you’re using JavaScript on your page, you’ll can also check individual properties of the Modernizr object for a boolean value – true means the feature is supported.

001 <style>
002  .no-csscolumns body {
003    /* this browser doesn’t support CSS columns */
004   }
005 </style>
006 <script>
007 if (Modernizr.touch) {
008   // the browser supports touch events, so run the code within this section
009 } else {
010  // the browser doesn’t support touch, so     provide an alternative 
011 }

Using your test results

Testing for the features that you’re targeting happens automatically as part of your build of Modernizr. As soon as the library is included in your page, the tests are run and the result is saved to the JavaScript Modernizr object, alongside a series of HTML-element classes indicating support for (or lack of support for) individual features being tested against.
So, now that you have this information, what do you do with it?

CSS-only customisation

For CSS-specific customisations, it’s as simple as providing an alternative set of rules that uses the class system to target browsers that don’t support the feature in question separately from those that do. For example, you might have one set of rules introducing a CSS transition for browsers that support animation, and a second set for those that don’t.
The CSS selector for those that support animations would be

001 .cssanimations [your normal selectors] { 
002 /* CSS rules in here */
003 }

While for those that don’t, the following selector would be applicable:

004 .no-cssanimations [your normal selectors]     { 
005 /* CSS rules in here */
006 }

Script customisation

Not everything can be handled with CSS alone. In the example above where we wanted to provide an alternative to CSS animation, JavaScript would offer a good solution. We could provide animation using CSS if supported, but fall back to a jQuery animation in browsers that don’t support CSS animations. In this case, we could use a simple jQuery selector to only run the JavaScript animation on non-supported browsers:
001 $(“.no-cssanimations [your normal     selectors]”).    each(function(){
002    // normal jQuery animation code
003 }

An alternative is to use the Modernizr object to retrieve the status of support for a particular feature. In the case of geolocation, for example, you might add a conditional clause in your script as follows:

001 If (Modernizr.geolocation) {
002    // This code only runs if the browser     supports geolocation
003 }

CSS and script customisation

If you need to customize both your scripts and your CSS, you can use a combination of both the methods above to provide support for both. This is particularly useful if you want to use a single JavaScript file and a single CSS document in your page.

Conditional loading of styles and scripts

If you’re able to split out your code into separate sections, the addition of YepNope allows you to conditionally load resources according to the result of each test. A major benefit of conditionally loading scripts and styles according to browser feature-support is that you avoid having to load all your workaround options into every browser; only those that need the polyfills get them. Check out the next page for full details on how to use YepNope with Modernizr!

Using polyfills
The whole purpose of Modernizr is to allow you to use modern features with safety, providing the opportunity to put a fallback or alternative ‘polyfill’ in place for browsers that don’t support a specific feature. Rather than re-invent the wheel each time that you need to polyfill a specific feature, the team behind Modernizr has compiled a list of pre-built polyfill options, categorized by feature. You can access this list at http://bit.ly/10S2kHA.

Loading CSS and JS files with Modernizr

Modernizr has a handy load method which can be optionally included within your build. This method was spun out as the YepNope project, but originates within the Modernizr library and includes a series of useful features that can boost the apparent download speed of your page, as well as conditionally load resources according to browser capability.
The basic syntax for loading a CSS or JavaScript file using Modernizr.load is shown below:

001 Modernizr.load([
002   // object notated list of tests and     responses
003  {
004   test : Modernizr.canvas && Modernizr.    cssgradients,
005   // Multiple resources can be loaded for     each     condition
006   // This condition is not met, so load     two     files…
007   nope : [‘presentational-polyfill.js’,     ‘presentational.css’]
008  },
009  {
010    // This just has to be truthy
011    test : Modernizr.JSON,
012    nope : ‘functional-polyfills.js’,
013    // These resources will be loaded     014     regardless of the result:
015    both : [ ‘app.js’, ‘extra.js’ ],
016    complete : function () {
017      // Run this after everything in this     group has downloaded
018      // and executed, as well everything in all previous groups
019      myApp.init();
020    }
021  },
022  // Run your analytics after you’ve     already     kicked off all the rest
023  // of your app.
024  ‘post-analytics.js’
025 ]);

You’ll notice that the final element in the object is a simple filename. In the absence of a test, the notated file will be simply loaded, allowing you to offset the loading of resources until your code is executed. This can give the impression of a faster loading page.

Setting up your own tests

The Modernizr API provides direct access to a number of useful methods that you can use to add your own bespoke tests. The example provided in the documentation for the library, which can be found at http://modernizr.com/docs/, demonstrates the addition of a test for support of the <track> element:

001 // Test for <track> element support
Modernizr.addTest(‘track’, function(){
002  var video = document.            createElement(‘video’);
003  return typeof video.addTextTrack ===     004 ‘function’
005 });

This extensibility allows you to add tests for cutting-edge or experimental browser features that aren’t available cross-browser. And, test progressive enhancements without adversely affecting non-supporting browsers or being reliant upon the library updating to test for features you want to test against.

Using YepNope with Modernizr

YepNope makes it easy to load JavaScript and CSS resources into your page according to the result of each Modernizr test.
We’ll show you how to use the library to only load content each browser needs.

1. Load the library
YepNope can either be downloaded on its own from www.yepnopejs.com, or you can include it directly in your Modernizr build by ticking the Modernizr.load checkbox under the Extra section. If you have included it in your Modernizr build, then you only need to include that particular file. If you’re keeping it separate, add a <script> tag in the head section of your page, linking to the yepnope.js file.

2. The basic syntax
The basic syntax for a YepNope conditional load is very simple and easy to understand. The YepNope object is called and a series of properties are passed in representing the test to perform and the resources to load. The example below loads a polyfill script for browsers that do not support HTML5 video.

001 yepnope({
002   test: Modernizr.video,
003   yep: ‘video.css’,
004   nope: [‘video-html5.css’,’video-    polyfill.    js’],
005   callback: function(url, result, key){
006     if(url == ‘video- html5.css’){
007       alert(“HTML5 Video Ready”);
008     }    
009 )};

3. Load resources
As well as loading on the basis of the result of the test, you can also use YepNope to load resources regardless of the test. There are further methods for handling events associated with the load of these resources (such as initiating an object), callback and complete – the latter being fired once everything has loaded and processed.

001 Yepnope({
002   test: /* condition to be tested, with a     boolean result (true / false) */,    
003   yep: /* list of resources to load if     condition is true */,
004   nope: /* list of resources to load if     condition is false */,
005   both: /* list of resources to load         regardless of result */
006 });

  • Tell a Friend
  • Follow our Twitter to find out about all the latest web development, news, reviews, previews, interviews, features and a whole more.