Since jQuery broke onto the scene, which now seems like a century ago, JavaScript libraries have become ubiquitous. Even the biggest fan must admit we are reaching saturation point. That said, there is a gem of a library that every developer must add to their toolbox; this little number goes by the name Modernizr.
What’s the fuss?
Mordernizr was originated by Faruk Ateş but has since got some heavy weights on board such as Paul Irish, and Alex Sextion. Based on the principles of progressive enhancement and graceful degradation, Modernizr detects browser support for the latest web technologies specifically HTML5 and CSS3 features including opacity, canvas, box shadow, svg, HTML5 input types, local and webStorage, geolocation and much, much more. This aids the developer in enhancing their web applications by providing useful information on support of a given web technology without resorting to the generally bad practice of user-agent(UA) sniffing. Conversely, if a certain feature is not supported, Modernizr will enable the developer to target a particular browser by providing a ‘hook’ in the DOM.
So how does it work?
Modernizr adds a CSS class to the root of the html
element of your document. So for example if I were working with canvas, it would add a canvas class where this technology is supported and no-canvas where it isn’t. I can then deal with both scenarios accordingly.
Saying that Modernizr is just a feature detection library is however selling it short. It can also be used to conditionally load scripts, build custom tests, and test media queries as I will demonstrate later. In the meantime here is a quick illustration of what Modernizr brings to the table.
Applying canvas using feature detection
No, that is not an image. In the trivial example above, we test for canvas support in the host browser before creating a canvas element and drawing a simple line. If you view this page in a browser that does not support canvas, you will get a friendly message encouraging you to upgrade your browser. In a real application, you might opt for a polyfill as a fallback solution for non-supporting browsers.
So how do I use it?
Modernizr is easy to use.
Step 1: Get a copy of Modernizr
Head off to modernizr.com and grab yourself a copy of the latest version of the Modernizr. You can download the full copy of the library, but chances are you only need a ‘diet’ version. In which case, the site provides a very handy tool that allows you to customize your download.
Step 2: Add to page
Script in hand, lets create a regular html document and add the Modernizr script to the page as we would any other script. Also add a ‘no-js‘ class to the html element. This will be replaced with ‘js‘ if Modernizr is running, but its also a cue to cases where JavaScript is not running and allows you to handle this scenario appropriately.
Link to script
<!DOCTYPE html> <html class="no-js"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> <meta name="viewport" content="width=device-width,initial-scale=1"> <script src="js/mordernizr.js"></script> <title>Do you support flexbox</title> </head> <body> <h1>Flexbox support</h1> <p></p> </body> </html>
Voilà! We are good to go. A quick glance at DOM, we see a array of classes added to the html
element and the ‘no-js‘ class replaced with ‘js‘. Of course if we only want to test support for a handful of properties/features then modernizr.com provides a tool for configuring your download.
Step 3: have fun
As of writing, canvas is not supported cross-browser so it makes a very good candidate. I will demonstrate both the CSS and JavaScript approaches.
CSS approach
.canvas #square{ /*-- styles for #square element in browser with canvas suppport --*/ } .no-convas #square{ /*-- styles for #square element in browser with no canvas support --*/ }
In the above snippet, .canvas and .no-canvas CSS rules target element #square for canvas and non-canvas supporting browsers respectively. These classes are dynamically appended to the html
element by Modernizr.
In the JavaScript variant, all the classes are properties of the Modernizr object making it easy to test for feature/property support.
JavaScript approach
var el = $('#square'); //Set the background color based on canvas support Modernizr.canvas ? el.css({'backgroundColor':'#f0f'}) : el.css('backgroundColor':'#ccc'); }
Note: Modernizr.canvas or any other property on the Modernizr object returns a boolean (true or false). And there you have it. But we are not done yet, there is more.
Load scripts conditionally
Within Modernizr, is a small library called YepNope. This is fundamentally a resource loader that facilitates conditional loading of both JavaScript and CSS files. For example, if we wanted to load FlashCanvas (canvas polyfill) for browsers that do not support canvas, we would use Modernizr as follows:
Modernizr.load()
Modernizr.load(){ test:Modernizr.canvas, nope:js/flashcanvas.js }
YepNope will load files asynchronously or in parallel which will make our applications perform better. Be sure to read more about Modernizr.load() as it has more tricks under its sleeve. Some of the useful properties include;
- load: loads a script or file and,
- complete: a callback function. Analogous to success in Ajax
Testing media queries
Modernizr provides a neat way of testing media queries using JavaScript. Say hello to Modernizr.mq(). This little bad boy takes a media query as an argument and will return a boolean. For example, if we want to improve user experience on a small device by removing certain page elements from small screens, we can do the following;
Modernizr.mq()
if(Modernizr.mq("screen and (max-width:480px)")){ //remove secondary navigation from small screens $('#secondary-nav').remove(); }
Summary
I hope I have managed to whet your appetite enough for you to give Modernizr a try. The library brings a lot to the table and I am sure you will at some point in your projects find it very useful. That said, tread carefully while using it especially when writing CSS. Think of a scenario where the user has turned off JavaScript (yes, people still do), or if the script does not load for one reason or another.