{"id":8678,"date":"2011-03-13T11:50:01","date_gmt":"2011-03-13T18:50:01","guid":{"rendered":"http:\/\/css-tricks.com\/?p=8678"},"modified":"2011-08-09T21:10:26","modified_gmt":"2011-08-10T04:10:26","slug":"progressively-enhancing-html5-forms","status":"publish","type":"post","link":"https:\/\/css-tricks.com\/progressively-enhancing-html5-forms\/","title":{"rendered":"Progressively Enhancing HTML5 Forms"},"content":{"rendered":"
This is what I’m thinking is the best current way to progressively enhance forms. That is, use HTML5 features when they are available and fall back to JavaScript alternatives when they are not. <\/p>\n
<script src=\"scripts\/yepnope.js\"><\/script><\/code><\/pre>\nYepnope is a “script loader” which will load scripts conditionally<\/em>. You give it some kind of boolean value (true or false), if it’s true, it’ll load one set of scripts (or css), if it’s false, a different set. Where do we get that boolean value? From testing a feature with… <\/p>\nLoad up Modernizr<\/a><\/h3>\n<script src=\"scripts\/modernizr.js\"><\/script><\/code><\/pre>\nModernizr gives you the ability to test for HTML5 and CSS31<\/sup> features. For example, with Modernizr loaded, Modernizr.inputtypes.date<\/code> will be true if you are in a browser that supports inputs with a type of date property (Only Opera, since about version 9) and false if you are in a browser that doesn’t support the date type.<\/p>\n\nEven better:<\/strong> You can get a custom build of Modernizr with only the tests you need (input types and input attributes) with Yepnope also built in in the Modernizr 2 beta builder<\/a>.<\/p>\n<\/div>\nCombine the two<\/h3>\n
With both of these awesome tools ready to go, we can combine their powers:<\/p>\n
yepnope({\r\n test : Modernizr.inputtypes.date,\r\n nope : [\r\n \/\/ load scripts to simulate date type\r\n ]\r\n});<\/code><\/pre>\nWe don’t need a “yep” in this case, because “yep” means the browser supports it so we don’t need any help.<\/p>\n
What do we need for a fallback?<\/h3>\n
Since we’ve been using the HTML5 input type date as an example, let’s think about a fallback for that. jQuery UI has a pretty sweet datepicker<\/a>. jQuery is likely to help us solve a lot of fallback problems, so that’s going to be a solid choice. To make the date fallback work, we’ll need to load four resources:<\/p>\n\n- jQuery<\/li>\n
- jQuery UI<\/li>\n
- jQuery UI’s CSS<\/li>\n
- Our own script calling the datepicker<\/li>\n<\/ol>\n
Load ’em up<\/h3>\n
With our Yepnope\/Modernizr combo, that laundry list looks like:<\/p>\n
yepnope({\r\n test : Modernizr.inputtypes && Modernizr.inputtypes.date,\r\n nope : [\r\n\t'scripts\/jquery.js', \r\n\t'scripts\/jquery-ui.js',\r\n\t'css\/jquery-ui.css',\r\n\t'scripts\/datepicker.js'\r\n ]\r\n});<\/code><\/pre>\nOur custom script (loaded last<\/strong>, courtesy of Yepnope) is probably as simple as just calling the datepicker function as soon as possible:<\/p>\n\/\/ DOM ready function because we should probably\r\n\/\/ be doing this in the <head>\r\n$(function() {\r\n\t$(\"input[type='date']\").datepicker();\r\n});<\/code><\/pre>\nAnd now we get:<\/p>\n
\n\n\n\n<\/td>\n \nOpera 11<\/h4>\n
Native support, no extra scripts loaded<\/p>\n<\/td>\n<\/tr>\n
\n\n\n<\/td>\n \nFirefox 4<\/h4>\n
No native support, jQuery UI datepicker used.<\/p>\n<\/td>\n<\/tr>\n<\/table>\n
Keep it going<\/h3>\n
Date type support isn’t the only thing we can do here. Let’s say we want to use placeholder as well. Rock’n’roll, just use another yepnope test:<\/p>\n
yepnope({\r\n test : Modernizr.input.placeholder,\r\n nope : [\r\n\t'scripts\/jquery.js', \r\n\t'scripts\/placeholder.js'\r\n ]\r\n});<\/code><\/pre>\nNotice we are using jQuery again, and thus specifying the jQuery library script. Let’s say we are in a browser without support for either<\/em> date or placeholder and we plan to use jQuery for both<\/em> fallbacks. To do this the best way, we’ll combine the tests the require jQuery into it’s own yepnope block, so we don’t end up loading jQuery more than once.<\/p>\nyepnope([\r\n {\r\n test: Modernizr.input.placeholder || (Modernizr.inputtypes && Modernizr.inputtypes.date),\r\n nope: 'jquery.js'\r\n },\r\n {\r\n test : Modernizr.inputtypes && Modernizr.inputtypes.date,\r\n nope : [\r\n\t'scripts\/jquery-ui.js',\r\n\t'css\/jquery-ui.css',\r\n\t'scripts\/datepicker.js'\r\n ]},\r\n {\r\n test : Modernizr.input.placeholder,\r\n nope : 'scripts\/placeholder.js'\r\n }\r\n]);<\/code><\/pre>\nCooler Than Polyfills<\/h3>\n