Traditional browsers are not completely replaced at this time, making it difficult for you to embed the latest CSS3 or HTML5 features into your website. Modernizr came into being to solve this problem. As an open source JavaScript library, Modernizr detects browser support for CSS3 or HTML5 features. Modernizr is not trying to add features that are not supported by older browsers, but allows you to modify the page design by creating optional style configurations. It can also simulate features that are not supported by older browsers by loading customized scripts.
Modernizr is simple to use, but not omnipotent. Successful use of Modernizr depends heavily on your CSS and JavaScript skills. This guide allows you to learn how to set optional styles for browsers that do not support multi-columns or projections. In addition, you can learn how to get older browsers to validate forms that use the latest HTML5 required properties, and how to selectively load script files based on the browser's functionality.
Modernizr is a JavaScript library used to detect browser functionality support. Currently, by checking the browser's processing of a series of tests, Modernizr can detect 18 CSS3 functions and more than 40 functions about HTML5. It is more reliable than traditional ways to detect browser names (browser sniffing). The execution time of a complete set of tests takes only a few microseconds. In addition, the Modernizr website uses custom scripts to detect only elements of interest, thus achieving efficiency optimization.
When using Modernizr to detect CSS3 support, you do not need to have any JavaScript knowledge. You only need to insert a file into the web page, and it will then add a set of classes to the <html> tag of the page according to the browser's functionality. The names of the corresponding classes have met the standardization requirements and are easy to understand. For example, if the browser supports the box-shadow property, you need to add the corresponding boxshadow class; otherwise, add a no-boxshadow class. All you have to do is create a style table that uses these classes to provide the appropriate style for the corresponding browser.
Modernizr makes it easy to implement JavaScript solutions, known as polyfills - it simulates HTML5-related features and technologies such as geolocation. However, you do need to have a basic understanding of JavaScript in order to use these features and technologies. The term polyfill comes from a British brand of clay that fills cracks (i.e., the filling material known to Americans). Here, polyfill is used to fill in the browser's functions. Sometimes Modernizr performs this task seamlessly. But essentially, this is just a patching job, so you can't rely on it to produce the exact same result achieved by a vulnerable browser.
Like other JavaScript libraries, Modernizr provides development and production versions. The only difference compared to most libraries is that spaces and comments have been removed from the production version, which reduces the size of downloads. Modernizr takes a different approach. The development version can be called a sink in a kitchen in a sense—it contains almost everything. The production version only contains those elements you choose, which can significantly reduce downloads. In many cases, the production version can be reduced to one-twentieth the size of the development version.
When testing with Modernizr, I recommend you download the development version. Once you have mastered how it works and its capabilities, you can download a custom production version for deployment on your website.
The sample file for this tutorial contains the development 2.0.6 version of Modernizr, but I suggest you replace it with the latest updated version from the Modernizr site.
Note: If you click the Download link in the main navigation menu by mistake, you will see a large number of check boxes appearing, asking you to select the tool you want. This is set for the customized version of production. Click the link to the Development version at the top of the panel, or click the Back button in your browser to return to the home page and select the Development button shown in Figure 1.
As mentioned earlier, Modernizr does not try to add new features to older browsers, but it allows you to make up for those missing features in your style. To show how this works, the example file contains a page called css_support_begin.html. If you load this page in a new browser, it should look like Figure 2.
Figure 2. Firefox 5 displays the page in multi-column format and adds shadows to the image The style of this page is to use column-count and box-shadow properties of CSS3 to display text in multi-column format and add shadows to the image. Older versions of browsers do not support any of these properties, so the same page in Internet Explorer (IE) 7 looks like Figure 3.
In IE9, the same page shows the image shadow, but the text is the same as the layout shown in Figure 3.
What you take in trying to make up for missing features depends on the requirements of your design outline. It will involve a lot of work to try to make the page look exactly the same in all browsers, but you can make some simple improvements, such as surrounding the text around the image, adjusting the left margins of the image to the text, and adding vague boundaries at the bottom and right edges of the image to make it feel like a more three-dimensional.
Modernizr uses JavaScript to detect the functionality supported by the browser, but instead of using JavaScript to dynamically load different stylesheets, it uses very simple techniques to add classes to the page's <html> tag. Then as a designer, it is up to you to decide to use CSS casing to provide the appropriate style for the target elements. For example, if the page supports the box-shadow property, Modernizr will add boxshadow class. If not supported, then it is added with the no-boxshadow class as a substitute.
Since browsers ignore CSS properties that they cannot recognize, you can use box-shadow property with confidence according to your basic style rules, however you need to add a separate descendant selector for older browsers in the following format:
.no-boxshadow img { /* styles for browsers that don't support box-shadow */ } Only browsers that do not support box-shadow will have no-boxshadow class, so other browsers will not apply this style rule.
Let's add Modernizr to the sample page and check the classes it adds to the <html> tag.
<!DOCTYPE HTML> <html> <!DOCTYPE HTML> <html class=no-js>Modernizr relies on JavaScript enabled in the browser. When it is enabled, this class is deleted dynamically. However, in rare cases, JavaScript is still present in HTML makup when it is not enabled, which allows you to create special style rules for such visitors if necessary.
</style> <script src=js/modernizr.js></script> </head> Note: If you use the Insert panel or the Insert menu, Dreamweaver will add type=text/javascript to the initial <script> tag. This is no longer required in HTML5, but keeping it will not cause any harm.
Note: If your Dreamweaver version does not have Live Code (or you are using a different HTML editor), you can check the generated code using development tools provided by most new browsers or Firebug provided by Firefox browsers.
As shown in Figure 4, the no-js class has been replaced by js class, which indicates that JavaScript has been enabled.
Table 1 lists the class names used by Modernizr to indicate support for CSS3. If a function does not support it, the name of the corresponding class is prefixed with no- .
Table 1. CSS3 functions detected by Modernizr
CSS Features | Modernizr class (properties) |
@font-face | fontface |
::before and ::after pseudo-elements | generatedcontent |
background-size | backgroundsize |
border-image | borderimage |
border-radius | borderradius |
box-shadow | boxshadow |
CSS animations | cssanimations |
CSS 2D transformations | csstransforms |
CSS 3D transformations | csstransforms3d |
CSS transitions | csstransitions |
flexible box layout | flexbox |
Gradients | cssgradients |
hsla() | hsla |
multi-column layout | csscolumns |
multiple backgrounds | multiplebgs |
opacity | opacity |
reflection | cssreflections |
rgba() | rgba |
text-shadow | textshadow |
No matter where a specific CSS attribute is tested, the class name and property name are the same, however this requires the removal of any hyphen or brackets. Other classes are named after the CSS3 module they refer to.
See Table 1, you can see that Modernizr uses boxshadow and csscolumns to show support for box-shadow properties and multi-column layout, respectively. Therefore, you can use the no-boxshadow and no-csscolumns classes to create special style rules for browsers that do not support these features.
To ensure the directive is simple, I will demonstrate an example of CSS declarations only. You can type them directly into the Code view or use the New CSS Rule dialog box.
.no-boxshadow img . #8A8A8A ). The resulting style rules should look like this:.no-boxshadow img { border-right: #8A8A8A 2px solid; border-bottom: #8A8A8A 2px solid; }This is not as attractive as translucent shadows, but despite this, it still allows the image to protrude slightly from the background.
.no-csscolumns img . .no-csscolumns img { margin: 3px 8px 3px 0; float: left; } .columns img rule. The two rules have the same particularity, so if they are reversed, the 10-pixel left margin of .columns img may overwrite the new rule you just created. You can rename .no-csscolumns img to .no-csscolumns .columns img to give it higher specificity, but it is best to ensure that the simpler the selector, the better. (By the way, if you're not sure what the particularity is, check out the article by Adrian Senior, Understanding Specificity. It's been published for a long time, but it's valuable.) In this simple example, I created special styles for older versions of browsers by using only the class prefixed with no- . However, by their ability, it is absolutely no point for you to use both classes (with or without prefixes) to create different styles for your browser. For example:
.csscolumns { /* rules for browsers that support multi-column layout */ } .no-csscolumns { /* rules for browsers that don't support multi-column layout */ }Sometimes this approach is reasonable, for example, if you want to create a completely different layout for each level of support. But if it's just a matter of providing selectable styles for older browsers, don't forget that the browser ignores properties that they don't recognize. If you use the Modernizr class for all styles, your page will be completely unstyled in a JavaScript-disabled browser.
Modernizr adds the class name for the starting <html> tag to play a dual purpose. When the pages are loading, they are also the names of the JavaScript properties created by the Modernizr object. Table 1 lists the names of classes and attributes related to CSS. Table 2 lists the remaining classes and attributes related to HTML5 and related technologies, such as geographic locations.
Table 2. HTML5-related features detected by Modernizr
HTML5 related features | Modernizr class (properties) |
Application cache | applicationcache |
Audio | audio. type (ogg, mp3, wav, m4a) |
Canvas | canvas |
Canvas text | canvastext |
Drag and drop | draganddrop |
Form input attributes | input. attributeName |
Form input elements | inputtypes. elementName |
Geolocation | geolocation |
hashchange event | hashchange |
History management | history |
IndexedDB | indexeddb |
Inline SVG | inlinesvg |
Local storage | localstorage |
Messaging | postmessage |
Session storage | sessionstorage |
SMIL | smil |
SVG | svg |
SVG clip paths | svgclippaths |
Touch events | touch |
Video | video. type (ogg, webm, h264) |
WebGL | webgl |
Web sockets | websockets |
Web SQL database | websqldatabase |
Web workers | webworkers |
In most cases, all attributes listed in Table 1 and Table 2 return true or false . So, you can test local storage using JavaScript as shown below:
if (Modernizr.localstorage) { // script to run if local storage is supported } else { // script to run if local storage is not supported } However, in terms of audio and video , the return value is a string that indicates that the browser is able to handle a certain type of confidence level. According to the HTML5 specification, an empty string means that the type is not supported. If this type is supported, the return value is maybe or probably. For example:
if (Modernizr.video.h264 == ) { // h264 is not supported } HTML5 adds many new form properties, such as autofocus , which automatically places the cursor in a specified field when the page is loaded for the first time. Another useful property is required , which will prevent HTML5-compatible browsers from submitting forms if a required field is left blank (see Figure 6).
This is great, but it will leave you with a question: What should you do with older versions of your browser?
One solution is to ignore them and leave them to the server-side verification function for final checks. If the browser does not recognize the required attribute, another user-friendly way to handle this situation is to create a small script to check the required fields. The following instructions show how to perform corresponding operations with the help of Modernizr.
</style> <script src=js/modernizr.js></script> </head> <script> block, and create an event handler as soon as the page is loaded to facilitate code execution:<script src=js/modernizr.js></script> <script> window.onload = function() { // code to execute when page loads }; </script> </head autofocus and required properties. The way to deal with autofocus is simple:window.onload = function() { // get the form and its input elements var form = document.forms[0], inputs = form.elements; // if no autofocus, put the focus in the first field if (!Modernizr.input.autofocus) { inputs[0].focus(); } // if required not supported, emulate it } This condition tests Modernizr.input.autofocus , if autofocus is not supported, the returned value is false . However, the logical operator NOT (an exclamation mark) can reverse the meaning, so if autofocus is not supported, the evaluation result of this condition is true , and inputs[0].focus() places the cursor in the first input field.
required is not supported, now add code to facilitate checking required fields. The complete code of the event handler is as follows:window.onload = function() { // get the form and its input elements var form = document.forms[0], inputs = form.elements; // if no autofocus, put the focus in the first field if (!Modernizr.input.autofocus) { inputs[0].focus(); } // if required not supported, emulate it if (!Modernizr.input.required) { form.onsubmit = function() { var required = [], att, val; // loop through input elements looking for required for (var i = 0; i < inputs.length; i++) { att = inputs[i].getAttribute('required'); // if required, get the value and trim whitespace if (att != null) { val = inputs[i].value; // if the value is empty, add to required array if (val.replace(/^/s+|/s+$/g, '') == '') { required.push(inputs[i].name); } } } // show alert if required array contains any elements if (required.length > 0) { alert('The following fields are required: ' + required.join(', ')); // prevent the form from being submitted return false; } }; } } The new code produces a function that when submitting the form it can iterate through all input elements to find fields with required attributes. When it finds a field, it removes the beginning and ending blanks from the value, and if the result is an empty string, it adds the result to required array. After all fields have been checked, if some elements are included in the array, the browser displays a warning related to the missing field name and prevents the form from being submitted.
Note: Safari 5.1 incorrectly reported that it supports required property, so it submits the form without validating the required fields. This is a flaw of Safari, but in Modernizr it does not exist.
When you are ready to deploy your website, it is recommended to create a custom product version of Modernizr that contains only those elements you actually need. This can reduce the size of the Modernizr library from 44KB to 2KB according to the functionality you selected. The range of the current options is shown in Figure 8.
Figure 8. Modernizr download page allows you to select only those features you needOptions can be easily grouped in the following categories: CSS3, HTML5, Misc(ellaneous) and Extra. Click the Toggle button next to the first three titles to select or discard all check boxes in the selection category.
By default, the Extra category will select the following three entries:
If you select any option in the CSS3 category, the options in the following Extra category will also be selected:
Modernizr.testProp() Modernizr.testAllProps() Modernizr._domPrefixes()Do not deselect these options. Doing so will automatically cancel any options you have selected in the CSS3 category.
MQ Polyfill (respond.js) in the Extra category has added a script that allows media queries in IE 6-8 to get limited support. When you select this option, it automatically selects Media Queries and Modernizr.testStyles(). To learn more about media queries polyfill (respond.js), visit https://github.com/scottjehl/Respond.
Only advanced users will be interested in other options in the Extra category. For more details on what they are and how to use them, see the Extensibility section of the Modernizr documentation.
The following description describes how to create a custom product version of Modernizr for the sample file. This custom version is required for subsequent exercises, which will show how to load external JavaScript files using Modernizr.load() .
When creating a custom production version of Modernizr, the option containing Modernizr.load() must be selected by default. Modernizr.load() is an alias for yepnope() , which is a standalone script loader developed synchronously with Modernizr. To illustrate how to use it, I give a simple example. I've moved the corresponding script from required.html to check_required.js and made three minor changes to facilitate the removal of Modernizr tests and assigning it to a variable called init . The revised script looks like this:
var init = function() { // get the form and its input elements var form = document.forms[0], inputs = form.elements; // put the focus in the first input field inputs[0].focus(); // check required fields when the form is submitted form.onsubmit = function() { var required = [], att, val; // loop through input elements looking for required for (var i = 0; i < inputs.length; i++) { att = inputs[i].getAttribute('required'); // if required, get the value and trim whitespace if (att != null) { val = inputs[i].value; // if the value is empty, add to required array if (val.replace(/^/s+|/s+$/g, '') == '') { required.push(inputs[i].name); } } } // show alert if required array contains any elements if (required.length > 0) { alert('The following fields are required: ' + required.join(', ')); // prevent the form from being submitted return false; } }; }; A big advantage of Modernizr.load() is that it can load scripts conditionally based on the results of testing browser capabilities—that is why it was called yepnope() at first. It can load external scripts asynchronously—in other words, it can load external scripts after the browser has loaded Document Object Model (DOM)—so it can help improve your website performance.
The basic syntax of Modernizr.load() is to pass an object with the following attributes to it:
test : The Modernizr property you want to detect. yep : If the test is successful, the location of the script you want to load. Use a multi-script array. nope : If the test fails, the location of the script you want to load. Use a multi-script array. complete : A function that runs as soon as an external script is loaded (optional). Both yep and nope are optional, as long as you provide one of them.
In order to load and execute scripts in check_required.js, you need to add the following <script> block after modernizr.adc.js has been attached to the page (the code is located in required_load.html):
<script> Modernizr.load({ test: Modernizr.input.required, nope: 'js/check_required.js', complete: function() { init(); } }); </script> This is exactly the same as before, but it can reduce the download load of browsers that already support required attribute.
To test multiple conditions, you can pass a set of objects to Modernizr.load() . For more details, see the Modernizr.load() tutorial on the Modernizr documentation.
Modernizr is a powerful and useful tool, but that doesn't mean you should use it. Not all cases are required to use Modernizr to provide multiple styles to the browser. If your main focus is Internet Explorer, consider using IE conditional comments. You can also use CSS stack to overwrite some styles. For example, use hexadecimal color first, and then override it with rgba() or hsla() . Older versions of browsers will use the first value and ignore the second value.
Modernizr really becomes a reality when it is combined with polyfills and other JavaScript. But remember, it is usually easy to create your own tests that are suitable for supporting features. For example, the following is all the code you test whether a browser supports required attribute (the code is located in required_nomodernizr.html):
var elem = document.createElement('input'); if (typeof elem.required != 'boolean') { // required is not supported }This tutorial has covered all the main features of Modernizr. For more information about these features, please refer to the corresponding official documentation, which is located at http://www.modernizr.com/docs/. In addition, you can find the following useful resources:
yepnope() , which has been merged into Modernizr.load() in Modernizr. +