Modernizr—the frontend developer's Swiss army knife

The web community's ability to figure out the many and varied issues of cross browser compatibility and create solutions for mere mortals like myself never ceases to amaze and delight me. Modernizr was mentioned briefly in Chapter 4, HTML5 for Responsive Designs and again in the last chapter. To reiterate, Modernizr is an open source JavaScript library that feature tests a browser's capabilities. Fauk Ateş wrote the first version, and the project now also includes Alex Sexton and the incredibly talented Paul Irish as the lead developer. It's a tool of choice for a few companies you may have heard of—Twitter, Microsoft, and Google. I mention this not merely to blow smoke up the Modernizr team (although they certainly deserve it) but more to illustrate that this isn't merely today's great piece of JavaScript. Put bluntly, it's a tool that is worth understanding.

So what does it actually do? How does it enable us to both polyfill older browsers and progressively enhance the user experience for newer ones and how do we make it do what we need? Read on grasshopper...

In terms of actions, Modernizr does little, by default, other than add Remy Sharp's HTML5 shim (when selected) to enable structural HTML5 elements such as <aside> and <section> in non-HTML5 capable browsers such as IE 8 and lower versions. What it does is "feature test" the browser. Consequently, it knows whether said browser supports various features of HTML5 and CSS3. This then provides the means to take a different action depending upon that information. The rest is for us to implement. So, let's add Moderniz to our pages and make a start.

First, download Modernizr (http://www.modernizr.com).

Tip

Which version of Modernizr—development or production?

If you're interested in how it works, grab the development version of Modernizr as each option/test is documented. However, using the production option allows you to select only the tests that are relevant to the site or web application you are building, keeping the file nice and lean

Modernizr—the frontend developer's Swiss army knife

Now, save the file to a suitable location (as before I've used a js folder in the root). And then call the file in <head> of your page:

<head>
<meta charset=utf-8>
<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1" />
<title>And the winner isn't…</title>
<link href="css/main.css" rel="stylesheet" />
<script src="js/modernizr.js"></script>
</head>

With Modernizr added, when viewing the source code of a page in Firebug or similar, it shows a variety of different classes added to the HTML tag. Here's an example from Firefox v9.01:

<html class=" js flexbox geolocation postmessage indexeddb history websockets rgba hsla multiplebgs backgroundsize borderimage borderradius boxshadow textshadow opacity cssanimations csscolumns cssgradients no-cssreflections csstransforms no-csstransforms3d csstransitions fontface generatedcontent video audio localstorage sessionstorage applicationcache" lang="en"> 

This is great. It tells us, on a browser-by-browser basis, what features it has tested and which features the browser does or doesn't support (where there is no support for a feature, it prefixes the feature with no-). This lets us do two major things—fix styling issues on a feature-by-feature basis in our CSS files and also conditionally load additional CSS or JS files only when needed.

Fix styling issues with Modernizr

Our responsive And the winner isn't… site is presenting the perfect opportunity to fix a problem with Modernizr. Whilst the Quiz page (http://www.andthewinnerisnt.com/3Dquiz.html) works fine in browsers (such as Safari and Chrome) that support 3D transforms it's just a simple hover effect in browsers that don't. Currently, regardless of whether a browser can render the 3D transforms or not, we have a note telling people: This page relies on 3D transforms. If the posters don't flip on hover, try viewing in Safari or Chrome.

But thanks to Modernizr's additional classes, we now have a means of only showing a relevant note if their browser doesn't have the 3D transform feature.

.note {
  display: none;
}
.no-csstransforms3d .note {
  display: block;
}

Breaking that down, first we set the CSS to not show the note by default:

.note {
  display: none;
}

This means browsers that have the CSS 3D Transform feature (Google Chrome 16 for example) won't see the note (see the following screenshot):

Fix styling issues with Modernizr

Then the second rule uses the additional class added by Modernizr to show the note for browsers that don't have the 3D transforms feature:

.no-csstransforms3d .note {
  display: block;
}

The following screenshot shows the same page in Firefox 9:

Fix styling issues with Modernizr

Modernizr allows us to stop thinking in terms of browsers and think in terms of features.

Modernizr adds HTML5 element support for old IE

As I've chosen a custom production version of Modernizr, that includes the HTML5 shim, refreshing the page in Internet Explorer 8 reveals a web page (as shown in the following screenshot) that looks a whole lot better than it did before:

Modernizr adds HTML5 element support for old IE

I didn't need to do anything more. Because Modernizr has enabled HTML5 structural elements in old IE many standard CSS styles are now understood and the page renders as it should.

For my money, that is perfectly usable. If you hadn't seen the same site in a modern browser you wouldn't necessarily know anything was different. However, due to IE8's lack of support for CSS3, we know there are some obvious visual shortcomings compared to a modern browser; there are no alternate colors in the navigation links (if needed we could easily fix this by adding an extra class to odd navigation links), no rounded corners on the button, no text or box shadows and perhaps more importantly, although our fluid grid flexes, a lack of CSS3 support means no media query support. No media queries—no significant layout changes at differing viewports in Internet Explorer 6, 7, or 8.

Although I don't consider this layout "broken" in any way, a tool such as Modernizr does give us the capability to add features that polyfill older browsers as we see fit. To illustrate, let's add media query min/max-width support so that our design responds to different viewports in Internet Explorer 6, 7, and 8.

Add min/max media query capability for Internet Explorer 6, 7, and 8

The polyfill that I generally use to add media query support to older versions of Internet Explorer only adds support for min/max-width media queries. There are more substantial media query polyfills that add a greater range of media query support but for a responsive design, Respond.js by Scott Jehl is simple to use, fast, and has always served me well.

Respond.js (https://github.com/scottjehl/Respond) can actually be used without Modernizr—just add it to the page in question, and as the author Scott Jehl himself says, "Crack open Internet Explorer and pump fists in delight".

So, before we integrate Respond.js with Modernizer, let's do just that. Drop Respond.js straight into our page (just add it after the Modernizr file we already added) and check it does what we want for IE. To do this, download the file, save it in a suitable location, and link to it in the <head> section:

<head>
<meta charset=utf-8>
<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1" />
<title>And the winner isn't…</title>
<link href="css/main.css" rel="stylesheet" />
<script src="js/modernizr.js"></script>
<script src="js/respond.min.js"></script>
</head>

Now, once we load the page in Internet Explorer 8 and resize the browser window, we get our responsive design back (see the following screenshot):

Add min/max media query capability for Internet Explorer 6, 7, and 8

Great, we've added a polyfill that sorts out min- and max-width media queries in Internet Explorer but here's the rub: this thing is now being loaded for every browser that loads the page—whether they need it or not. One solution would be to stick the script link in an IE conditional comment like the following:

<!--[if lte IE 8]>
        <script src="js/respond.min.js"/></script>
<![endif]-->

I'm sure you've come across conditional comments before. They are a simple way of loading CSS or JS files (or even content) that only the relevant version of Internet Explorer will use. All other browsers will see the code as a comment and ignore it.

In this example, our conditional comment says, "If you are less than or equal to (the lte part) Internet Explorer 8, (the IE 8 part) do this".

Tip

All about conditional comments

Conditional comments are falling out of favor compared with feature detection but if you'd like to know more, read all about them at the following URL:

http://msdn.microsoft.com/en-us/library/ ms537512%28v=vs.85%29.aspx

That will work fine. But do we really want to litter our markup with IE specific conditional comments? And what about polyfills for other browsers? This is where Modernizr steps up to the plate.

Conditional loading with Modernizr

A big pull of Modernizr when trying to keep websites and web applications as lean as possible is that it can load resources (both CSS and JS files) conditionally. So, rather than use a "scatter gun" approach and laden our pages with every polyfill a user might need (regardless of whether they actually need them or not), we only load the polyfills a user actually needs. This keeps our pages and load times as lean as they can be for each and every user.

So with Modernizr already added to the head of our pages, let's use it to conditionally load our Respond.js polyfill only if the browser in question doesn't natively understand CSS3 media queries (for example IE versions 6, 7, and 8).

Modernizr includes a JavaScript micro-library called YepNope.js (http://yepnopejs.com/). It uses a simple format:

Modernizr.load({
    test: Modernizr.mq('only all'),
    nope: 'js/respond.min.js'
});

First up is the call to the resource loading part of Modernizr:

Modernizr.load({

Within this is the test itself and a number of possible actions based on the result of that test. In this example, we have asked if the browser understands a media query:

    test: Modernizr.mq('only all'),

If not, the resource should load our respond.min.js file:

    nope: 'js/respond.min.js'

Here only all is the equivalent of "do you understand media queries?" Old IE will always fail the test, resulting in nope and therefore load the relevant resource. This enables respond.min.js to only be loaded when needed.

We could also opt to load additional files at the same time:

Modernizr.load({
    test: Modernizr.mq('only all'),
    nope: ['js/respond.min.js', 'css/extra.css']
});

This example uses an array to add the respond.min.js file and a CSS file called extra.css . You may opt to load CSS this way to maintain separate styles that are only needed in the presence or absence of certain features. It's worth remembering that it's also possible to load different resources based on different outcomes:

Modernizr.load({
    test: Modernizr.mq('only all'),
    yep: 'js/pass.js',
    nope: 'js/respond.min.js'['fail-polyfill.js', 'fail.css'],
    both: 'js/for-all.js'
});

Here, we load one file if the browser passes, another two (in the array) if it fails and a final file if it passes or fails.

The conditional loading code tests can be written in another separate JavaScript file. In this instance, I have called mine the conditional.js file and saved it in the js folder, alongside modernizr.js and respond.min.js. So, the <head> section now looks as follows:

<head>
<meta charset=utf-8>
<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1" />
<title>And the winner isn't…</title>
<link href="css/main.css" rel="stylesheet" />
<script src="js/modernizr.js"></script>
<script src="js/conditional.js"></script>
</head>

Note that I've removed respond.min.js from the head as it's now loaded in conditionally as and when needed.

Note

More documentation on how to conditionally load resources with Modernizr can be found at http://www.modernizr.com/docs/#load

Tip

Get your polyfills here

Remember, there's a great repository (pun intended) of useful polyfills at the following Github location:

https://github.com/Modernizr/Modernizr/wiki/HTML5- Cross-browser-Polyfills

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.117.78.237