Modernizr

Modernizr

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 htmlelement 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.

Useful resources

Native HTML5 datepickers with a JavaScript fallback

HTML5 Datepicker

We’ve all seen them around the web. Focus in a date input field, and a calendar datepicker pops up allowing the user to select a date. Until the advent of HTML5 and jQuery UI, developers achieved this rather mean feat by way of manipulating table cells courtesy of JavaScript. Soon enough all modern browsers will natively support calendar datepickers. As a developer all you need to do is add type=”date” to your input field and watch the browser do its magic.

Unfortunately, not all browsers at the time of writing (AHEM, no name calling) support this attribute value. I will therefore make an attempt at saving the world by demonstrating how to implement a datepicker in your form fields (you can not say I did not try) while providing a JavaScript fallback for the those browsers that are yet to implement this attribute value.

The HTML

<!DOCTYPE html> 
<html> 
<head> 
   <title>HTML5 datepicker</title> 
</head> 
<body> 
   <form action=""> 
      <input type="date" name="date"> 
   </form> 
</body> 
</html>

In the HTML markup above, we have a simple input field with type=”date”. date is one of an array of new form input attribute values in the HTML5 specification. Try this out in Chrome, Firefox and Opera, and you get a calendar datepicker when the input field is in focus. This is however not the case for Internet Explorer 9 and below.

Show some mobile device love

Mobile browsers, native or otherwise, support most if not all the new HTML5 form input attribute values. This enhances the user experience as the on-demand virtual keyboard provided is appropriate to the input field in focus. So for example; if the input field has type=”email”, you are presented with a keyboard with symbols associated to email addresses e.g @ and the top level domain(.com) in some cases. But I digress, the whole chapter of HTML5 form input attributes warrants its own forum (watch this space).

In our case, the user is presented with a calendar datepicker. The image below is a screen grab from Chrome on a Android device. Splendid indeed eh?
Chrome for Android datepicker

Fallback – Hello IE and such!(Not so much love)

The beauty of the new HTML5 elements and attribute values is that if they are not supported by the browser, they fail silently or defaults are used. In our case, IE just treats it as if it were a text input (type=”text”). However since we do not want to be sued by our friends that refuse to update their browsers or choose to use Internet Explorer, we should strive to offer a similar user experience where humanly possible or degrade gracefully. JavaScript to the rescue. Below is the revised HTML code.

Revised HTML

<!DOCTYPE html>
<html>
<head>
   <title>HTML5 datepicker</title>
   <link rel="stylesheet" href="css/ui-lightness/jquery-ui-1.8.23.custon.css">
</head>
<body>
   <form action="">
      <input type="date" name="date">
   </form>
</body>
<script src="js/jquery-1.8.1.min.js"></script>
<script src="js/jquery-ui.js"></script>

//call the datepicker method on the date input field
<script>
   $('#date').datepicker();
</script>
</html>

jQuery has a user interface library with several ready-to-use plugins/widgets that are easy to implement and make adding common features such as tabs and accordions a breeze. It so happens that the UI includes a calendar datepicker widget that we can use in this case. To add the widget to your web application, stop over at jQuery UI where you will find a demo and documentation. jQuery provides an assortment of themes and you are bound to find one that suits your project.

Once you have decided on a theme, download the library. Be sure to customise your download by deselecting all first, then only adding core jQuery and the datepicker widget as you do not need the entire UI library. Do not forget to choose a theme before you click the download button otherwise your color picker will not have the CSS to your theme of choice.

As you may have noted in the revised HTML code above, I have added the jQuery UI script which has a dependency on jQuery core. I have also added the CSS that will give our datepicker the preferred theme/styling. You are now ready to apply the functionality to your input field.

Now simply call the datepicker method on the #date input field as demonstrated in the code above. You should obviously do this ‘unobstrusively’ by creating an external file, but for expedience and conciseness I have added the code at the bottom of the HTML file. And there it is folks, easy as pie, we have a cross browser datepicker. Yes, it works in IE too. Who knew?

There is however one problem, if you try out our new input field in a browser that supports this feature natively, you will notice that we are getting both the native and the jQuery plugin fallback solution, which is obviously not elegant. To solve this problem, we can add simple feature detection to our code to test weather the browser supports the date attribute value or not.

In the snippet below, we create an element and assign date to the type attribute, if the browser does not understand this value, it coerces the value to text. We then test whether our #date input type is text, if so, only then should we add the fallback. See code below and check out the demo;

Feature detection

<script>
   var el = document.createElement('input');
   el.setAttribute('type','date');
   //if type is text then and only then should you call the fallback
   if(el.type === 'text'){
      $('#date').datepicker({
         dateFormat:'dd-mm-yy'
      });
   }
</script>

Properties

The datepicker method can take an object as a parameter with an array of properties such as dateFormat, autoSize, minDate, maxDate that you can pass to customize the behaviour. For a definitive list, visit the demo URL above and click on options. For instance to set the date format, you would pass dateFormat:’dd-mm-yy’ as shown below

Change date format

<script>
  $('#date').datepicker({
   dateFormat:'dd-mm-yy'
  });
</script>

To wrap it up, I would recommend another very nice calendar plugin that I have used in the past by Andy Croxall of the mitya.co.uk fame. Feel free to give it a try.

That’s a wrap.