HTML5 & CSS3 FOR THE REAL WORLD (2015)

Appendix A. Modernizr

Modernizr is an open-source JavaScript library that enables us to test for individual features of HTML5, CSS3, and some APIs in our users’ browsers. Instead of testing solely for a particular browser and trying to make decisions based on that, Modernizr allows us to ask specific questions such as “does this browser support geolocation?” and receive a clear “yes” or “no” answer. Modernizr does this by feature detection: checking whether the browser that our user is currently utilizing supports a given feature.

The first step to using Modernizr is to download it from the website, where it’s recommended that you begin with the Development version—we agree! This version will test for every single feature of HTML5, CSS3, and the new APIs. This is a good idea when you’re starting your project, as chances are you’ll be a little unsure about all the different features you’ll be using.

Once you’re ready to move your project into production, you can return to Modernizr’s download page and create a custom build, checking off the particular features you’d like to detect. Why be so specific? Because it takes time for Modernizr to test for the presence of a given feature, it’s best for performance reasons to only check the HTML5 features that you’ll use, as shown in Figure A.1. A custom build of Modernizr will also be minified (which isn’t true of the Development version), so the size of the library will be much smaller.

Modernizr’s download page prompt

Figure A.1. Modernizr’s download page prompt

Once you have a copy of the library, you’ll need to include the file in your pages. We’ll add it to the head in this example:

<!DOCTYPE html>

<html>

<head>

<meta charset="utf-8">

<title>My Beautiful Sample Page</title>

<script src="modernizr-2.8.3.min.js"></script>

</head>

You can use Modernizr in two ways: with CSS, and with JavaScript. Let’s discover more.

Using Modernizr with CSS

When Modernizr runs, it will add a new class name to the html tag for every feature you have asked it to detect. It will prefix the feature with no- if the browser offers no support for it.

For example, if you’re using Safari 6.2—which supports almost everything in HTML5 and CSS3—and you use the development version of Modernizr—which checks for all available HTML5 features—your opening html tag will look a little like this after Modernizr runs (we're only showing a snippet of it to save space in this book):

<html class="js no-blobworkers no-adownload applicationcache

audiodata webaudio audio no-lowbattery no-batteryapi no-battery-api

blobconstructor blob-constructor canvas todataurljpeg todataurlpng

no-todataurlwebp canvastext contenteditable no-contentsecuritypolicy

no-contextmenu cookies cors cssanimations backgroundcliptext

bgpositionshorthand bgpositionxy bgrepeatround bgrepeatspace

backgroundsize bgsizecover borderimage borderradius boxshadow

boxsizing csscalc checked csscolumns cubicbezierrange

testobjfntrue testchainone testchaintwo testchainthree">

As you can see, the complete list of all the features Modernizr tests for is comprehensive! Again, as has been mentioned, this is great while you’re still testing. But once you’re ready for your website to move into production, you should create a custom build of Modernizr and test only for the features you intend to use in the project, ensuring you have the smallest amount of Modernizr code necessary for your project.

Once we’ve downloaded Modernizr and included it in our project, we then add the class no-js to our html element in our HTML source:

<html class="no-js">

Why do we do this? If JavaScript is disabled, Modernizr won’t run at all—but if JavaScript is enabled, Modernizr’s first job will be to change no-js to js. This way, you’ll have hooks to base your styles on the presence or absence of JavaScript.

You might be thinking, “That sounds pretty cool, but what am I actually supposed to do with this information?” What we can do is use these classes to provide two flavors of CSS: styles for browsers that support certain features, and different styles for browsers that don’t.

Because the classes are set on the html element, we can use descendant selectors to target any element on the page based on support for a given feature.

Here’s an example. Any element with a class of .ad2 that lives inside an element with a class of .cssgradients (in other words, the html element when Modernizr has detected support for gradients) will receive whichever style we specify:

.cssgradients .ad2 {

/* gradients are supported! Let’s use some! */

background-image: linear-gradient(#FFF 0%, #000 100%);

}

But what if CSS gradients aren’t supported? We could change the styling to use a simple PNG background image that recreates the same gradient look. Here’s how we might do that:

.no-cssgradients .ad2 {

background-image: url(../images/put_a_replacement_img_here.png);

}

Another way we could use the classes Modernizr adds to the html element is with Drag and Drop. We discussed Drag and Drop in Chapter 12, where we added several images of computer mice that can be dragged onto our cat picture to be eaten. These images are all stored in a div with an ID of mouseContainer.

In some mobile browsers, drag and drop will fail to work, so why show the mouse images at all? We can use Modernizr to hide the div if Drag and Drop is unsupported:

.no-draganddrop .mc { // mc is short for "mouse container"

visibility: hidden;

height: 0;

}

If Drag and Drop is supported, we simply align all the content in the div horizontally:

.draganddrop .mc {

text-align: center;

}

Using Modernizr with JavaScript

We can also use Modernizr in our JavaScript to provide some fallback if the visitor’s browser has no support for any of the HTML5 elements, CSS3 properties, or (some of) the APIs you use.

When Modernizr runs, as well as adding all those classes to your html element, it will also create a global JavaScript object that you can use to test for support of a given feature. Appropriately enough, the object is called Modernizr. It contains a property for every HTML5, CSS3, and API feature it can test.

Here are a few examples:

Modernizr.draganddrop;

Modernizr.geolocation;

Modernizr.textshadow;

Each property will be either true or false, depending on whether or not the feature is available in the visitor’s browser. This is useful, because we can ask questions such as “Is geolocation supported in my visitor’s browser?” and then take actions depending on the answer.

Here’s an example of using an if/else block to test for drag and drop support using Modernizr:

if (Modernizr.draganddrop) {

// go ahead and use the drag and drop API,

// it’s supported!

}

else {

// There is no support for drag and drop.

// We can use jQuery UI Draggable(http://jqueryui.com/)

// or the dropfile polyfill https://github.com/MrSwitch/dropfile

// instead

}

Further Reading

To learn more about Modernizr, see:

· the Modernizr documentation

· a fairly comprehensive and up-to-date list of polyfills for HTML5 and CSS3 properties that can be used in conjunction with Modernizr, maintained at the Modernizr wiki

· “Taking Advantage of HTML5 and CSS3 with Modernizr,” an A List Apart article