What is Modernizr?

Modernizr is a small piece of JavaScript code that automatically detects the availability of next-generation web technologies in your user's browsers. Rather than blacklisting entire ranges of browsers based on “UA sniffing,” Modernizr uses feature detection to allow you to easily tailor your user's experiences based on the actual capabilities of their browser.

With this knowledge that Modernizr gives you, you can take advantage of these new features in the browsers that can render or utilize them, and still have easy and reliable means of controlling the situation for the browsers that cannot.

What is feature detection?

In the dark ages of web development, we often had to resort to UA sniffing in order to determine if their user's would be able to make use of Awesome-New-Feature™. In practice, that means doing something like the following

Now that looks ok, right? We are using Awesome-New-Feature™, and of course it isn't supported in an old crusty browser like that, right? That could very well be the case - today. But what if the next version of that browser adds support for Awesome-New-Feature™? Now you have to go back and audit your code, updating every single place that you are doing this check. That is assuming that you have the time to find out about every feature update for every single browser. Worse still, until you realize that it actually works in the newest version, all of those users back at the office getTheOldLameExperience, for no reason whatsoever.

Those users - given a substandard website for apparently no reason - can actually go into their browser and OS settings and change the name of the browser (or user-agent - what we compare against in code when performing a UA sniff) to whatever they would like. At that point - your code is meaningless. You are blocking out users who may actually support all of your features, and possibly letting those in who don't. Nearly everyone gets a broken experience. There has to be a better way!

There is, and it is called Feature Detection, and it looks more like this

Rather than basing your decisions on whether or not the user is on the one-they-make-you-use-at-work browser, and assuming that means they either do or do not have access to Awesome-New-Feature™, feature detection actually programmatically checks if Awesome-New-Feature™ works in the browser, and gives you either a true or false result. So now as soon as your least favorite browser adds support for Awesome-New-Feature™, your code works there - automatically! No more having to update, ever. The code ends up being similar, but much more clear to its actual intention

Downloading Modernizr

A lot has changed since the last version of Modernizr. There no longer is a single, base modernizr.js file. Instead, just head over to the Download page as you could have previously, and select the features you want to use in your project. This way we can provide the smallest file possible, which means a faster website for you. Once you have done that, just hit the Build button and you’ve got your own custom build of Modernizr, hot off the presses!

You may notice that in addition to the Build output, where you have been able to download custom builds one at a time for years now - there are two new options.

Command Line Config

Since 3.0, Modernizr also ships its build system as a node module on npm. That means that you can quickly create multiple builds of Modernizr for different projects, without even having to open a new browser tab.

Once you have npm installed, you can install the Modernizr command line tool by running

npm install -g modernizr

Now you are ready to get your start making your custom build! You can download the configuration file from the build menu (under "Command Line Config"). This will give you a JSON file that you will give to the Modernizr module to make your custom build.

modernizr-cmodernizr-config.json

Note that you will need to give the command line config the file path to the configuration you downloaded from the site. In the above example, we are running the modernizr command from the same folder that we downloaded the modernizr-config.json file to.

Grunt Config

If you do not want to manually run your build from the command line every time you update your site, you also have the option to download a Grunt task to do it for you. This configuration file can be used with grunt-modernizr to automatically build your custom version. Just add it to your Gruntfile, and you are off to the races.

Note that you will need to update the provided configuration file with paths to the devFile and outputFile. More documentation is available for grunt-modernizr here

Configuration Options

In addition to the available options and feature detects, there are a handful of additional configuration options.

classPrefix - default: ""

A string that is added before each CSS class.

enableJSClass - default: true

Whether or not to update .no-js to .js on the root element.

enableClasses - default: true

Whether or not Modernizr should add its CSS classes at all

See the next section for more information on those options

Using Modernizr with CSS

Modernizr's classes

By default, Modernizr sets classes for all of your tests on the root element (<html> for websites). This means adding the class for each feature when it is supported, and adding it with a no- prefix when it is not (e.g. .feature or .no-feature). This makes it super simple to add features in via progressive enhancement!

Say you include Modernizr's detection for CSS gradients. Depending on the browser, it will result in either <html class="cssgradients"> or <html class="no-cssgradients">. Now that you know those two states, you can write CSS to cover both cases

classPrefix

If one of Modernizr's class names clashes with one of your preexisting classes, you have the option to add a classPrefix inside of your config. Consider the hidden detect, which adds a .hidden class - something a lot of code bases already use to, well, hide things. If you wanted to use that specific detection, you could use the following as your configuration

{
"classPrefix": "foo-",
"feature-detects": ["dom/hidden"]
}

This would mean that rather than <html class="hidden">, you would get <html class="foo-hidden">.

no-js

By default, Modernizr will rewrite <html class="no-js"> to <html class="js">. This lets hide certain elements that should only be exposed in environments that execute JavaScript. If you want to disable this change, you can set enableJSClass to false in your config.

enableClasses

If you are using a classPrefix, such as supports-, then you must include that prefix on your html element. ie. supports-no-js instead of no-js.

Finally, if you do not want Modernizr to add any of it's classes, you can set enableClasses to false. This does not effect the .no-js update, so if you do not want that updated either you will need to set enableJSClass to false in your configuration.

Using Modernizr with JavaScript

The Modernizr object

Modernizr keeps track of the results of all of it's feature detections via the Modernizr object. That means that for each test, a corresponding property will be added. You just have to test for truthiness in your code to figure out what you want to do

Helper methods

Modernizr optionally exposes a number of additional functions, that you can read more about in Modernizr API

Modernizr API

Modernizr.on

Modernizr.on(feature,cb)

Modernizr.on('flash', function( result ) {
if (result) {
// the browser has flash
} else {
// the browser does not have flash
}
});

Modernizr.addTest

Modernizr.addTest(feature,test)

The most common way of creating your own feature detects is by calling Modernizr.addTest with a string (preferably just lowercase, without any punctuation), and a function you want executed that will return a boolean result

When the above is run, it will set Modernizr.itstuesday to true when it is tuesday, and to false every other day of the week. One thing to notice is that the names of feature detect functions are always lowercased when added to the Modernizr object. That means that Modernizr.itsTuesday will not exist, but Modernizr.itstuesday will. Since we only look at the returned value from any feature detection function, you do not need to actually use a function. For simple detections, just passing in a statement that will return a boolean value works just fine.

Modernizr.addTest('hasJquery', 'jQuery'inwindow);

Just like before, when the above runs Modernizr.hasjquery will be true if jQuery has been included on the page. Not using a function saves a small amount of overhead for the browser, as well as making your code much more readable. Finally, you also have the ability to pass in an object of feature names and their tests. This is handy if you want to add multiple detections in one go. The keys should always be a string, and the value can be either a boolean or function that returns a boolean.

If you would just like to test that media queries are supported in general, use

Modernizr.mq('only all'); // true if MQ are supported, false ifnot

Note that if the browser does not support media queries (e.g. old IE) mq will always return false.

Modernizr.prefixed

Modernizr.prefixed(prop,[obj],[elem])

Modernizr.prefixed takes a string css value in the DOM style camelCase (as opposed to the css style kebab-case) form and returns the (possibly prefixed) version of that property that the browser actually supports. For example, in older Firefox...

prefixed('boxSizing')

returns 'MozBoxSizing' In newer Firefox, as well as any other browser that support the unprefixed version would simply return boxSizing. Any browser that does not support the property at all, it will return false. By default, prefixed is checked against a DOM element. If you want to check for a property on another object, just pass it as a second argument

Modernizr._prefixes

Modernizr._prefixes is the internal list of prefixes that we test against inside of things like prefixed and prefixedCSS. It is simply an array of kebab-case vendor prefixes you can use within your code. Some common use cases include Generating all possible prefixed version of a CSS property

Modernizr.testStyles

Modernizr.testStyles(rule,callback,[nodes],[testnames])

Modernizr.testStyles takes a CSS rule and injects it onto the current page along with (possibly multiple) DOM elements. This lets you check for features that can not be detected by simply checking the IDL.

If your test requires multiple nodes, you can include a third argument indicating how many additional div elements to include on the page. The additional nodes are injected as children of the elem that is returned as the first argument to the callback.

By default, all of the additional elements have an ID of modernizr[n], where n is its index (e.g. the first additional, second overall is #modernizr2, the second additional is #modernizr3, etc.). If you want to have more meaningful IDs for your function, you can provide them as the fourth argument, as an array of strings

Detects support for the window.registerProtocolHandler() API to allow websites to register themselves as possible handlers for particular protocols.

CustomEvent

customevent

Detects support for CustomEvent.

Dart

dart

Detects native support for the Dart programming language.

DataView

dataview

Detects support for the DataView interface for reading data from an ArrayBuffer as part of the Typed Array spec.

Emoji

emoji

Detects support for emoji character sets.

Event Listener

eventlistener

Detects native support for addEventListener

EXIF Orientation

exiforientation

Detects support for EXIF Orientation in JPEG images.

iOS looks at the EXIF Orientation flag in JPEGs and rotates the image accordingly. Most desktop browsers just ignore this data.

Flash

flash

Detects Flash support as well as Flash-blocking plugins

Force Touch Events

forcetouch

Tests whether the browser supports the detection of Force Touch Events. Force Touch Events allow custom behaviours and interactions to take place based on the given pressure or change in pressure from a compatible trackpad.

Force Touch events are available in OS X 10.11 and later on devices equipped with Force Touch trackpads.

Fullscreen API

fullscreen

Detects support for the ability to make the current website take over the user's entire screen

GamePad API

gamepads

Detects support for the Gamepad API, for access to gamepads and controllers.

Geolocation API

geolocation

Detects support for the Geolocation API for users to provide their location to web applications.

Hashchange event

hashchange

Detects support for the hashchange event, fired when the current location fragment changes.

Hidden Scrollbar

hiddenscroll

Detects overlay scrollbars (when scrollbars on overflowed blocks are visible). This is found most commonly on mobile and OS X.

History API

history

Detects support for the History API for manipulating the browser session history.

HTML Imports

htmlimports

Detects support for HTML import, a feature that is used for loading in Web Components.

IE8 compat mode

ie8compat

Detects whether or not the current browser is IE8 in compatibility mode (i.e. acting as IE7).

IndexedDB

indexeddb

Detects support for the IndexedDB client-side storage API (final spec).

IndexedDB Blob

indexeddbblob

Detects if the browser can save File/Blob objects to IndexedDB

Input attributes

input

Detects support for HTML5 <input> element attributes and exposes Boolean subproperties with the results:

Detects support for IE userData for persisting data, an API similar to localStorage but supported since IE5.

Vibration API

vibrate

Detects support for the API that provides access to the vibration mechanism of the hosting device, to provide tactile feedback.

HTML5 Video

video

Detects support for the video element, as well as testing what types of content it supports.

Subproperties are provided to describe support for ogg, h264 and webm formats, e.g.:

Modernizr.video // true
Modernizr.video.ogg // 'probably'

VML

vml

Detects support for VML.

Web Intents

webintents

Detects native support for the Web Intents APIs for service discovery and inter-application communication.

Chrome added support for this in v19, but removed it again in v24 because of "a number of areas for development in both the API and specific user experience in Chrome". No other browsers currently support it, however a JavaScript shim is available.

Web Animation API

animation

Detects support for the Web Animation API, a way to create css animations in js

WebGL

webgl

WebSockets Support

websockets

XDomainRequest

xdomainrequest

Detects support for XDomainRequest in IE9 & IE8

a[download] Attribute

adownload

When used on an <a>, this attribute signifies that the resource it points to should be downloaded by the browser rather than navigating to it.

Audio Loop Attribute

audioloop

Detects if an audio element can automatically restart, once it has finished

Audio Preload

audiopreload

Detects if audio can be downloaded in the background before it starts playing in the <audio> element

Determines if winding rules, which controls if a path can go clockwise or counterclockwise

getRandomValues

getrandomvalues

Detects support for the window.crypto.getRandomValues method for generating cryptographically secure random numbers

cssall

cssall

Detects support for the all css property, which is a shorthand to reset all css properties (except direction and unicode-bidi) to their original value

CSS Animations

cssanimations

Detects whether or not elements can be animated using CSS

Appearance

appearance

Detects support for the appearance css property, which is used to make an element inherit the style of a standard user interface element. It can also be used to remove the default styles of an element, such as input and buttons.

Backdrop Filter

backdropfilter

Detects support for CSS Backdrop Filters, allowing for background blur effects like those introduced in iOS 7. Support for this was added to iOS Safari/WebKit in iOS 9.

CSS Background Blend Mode

backgroundblendmode

Detects the ability for the browser to composite backgrounds using blending modes similar to ones found in Photoshop or Illustrator.

CSS Background Clip Text

backgroundcliptext

Detects the ability to control specifies whether or not an element's background extends beyond its border in CSS

Background Position Shorthand

bgpositionshorthand

Detects if you can use the shorthand method to define multiple parts of an element's background-position simultaniously.

eg background-position: right 10px bottom 10px

Background Position XY

bgpositionxy

Detects the ability to control an element's background position using css

Background Repeat

bgrepeatspace,bgrepeatround

Detects the ability to use round and space as properties for background-repeat

Background Size

backgroundsize

Background Size Cover

bgsizecover

Border Image

borderimage

Border Radius

borderradius

Box Shadow

boxshadow

Box Sizing

boxsizing

CSS Calc

csscalc

Method of allowing calculated values for length units. For example:

//lem {
width: calc(100% - 3em);
}

CSS :checked pseudo-selector

checked

CSS Font ch Units

csschunit

CSS Columns

csscolumns

CSS Grid (old & new)

cssgrid,cssgridlegacy

CSS Cubic Bezier Range

cubicbezierrange

CSS Display run-in

display-runin

CSS Display table

displaytable

display: table and table-cell test. (both are tested under one name table-cell )

CSS text-overflow ellipsis

ellipsis

CSS.escape()

cssescape

Tests for CSS.escape() support.

CSS Font ex Units

cssexunit

CSS Filters

cssfilters

Flexbox

flexbox

Detects support for the Flexible Box Layout model, a.k.a. Flexbox, which allows easy manipulation of layout order and sizing within a container.

Flexbox (legacy)

flexboxlegacy

Flexbox (tweener)

flexboxtweener

Flex Line Wrapping

flexwrap

Detects support for the flex-wrap CSS property, part of Flexbox, which isn’t present in all Flexbox implementations (notably Firefox).

This featured in both the 'tweener' syntax (implemented by IE10) and the 'modern' syntax (implemented by others). This detect will return true for either of these implementations, as long as the flex-wrap property is supported. So to ensure the modern syntax is supported, use together with Modernizr.flexbox: