Slide 1

Slide 1 text

No content

Slide 2

Slide 2 text

A little about me @addyosmani JavaScript & UI Developer @ AOL jQuery [Bug Triage/Docs/Learning] teams Written polyfills for Page Visibility API, WebKit speech input and more. I ! making the web better " " " " "

Slide 3

Slide 3 text

Why Do Polyfills Matter?

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

WebGL in IE6, 7 & 8 using JebGL (Video)

Slide 6

Slide 6 text

Canvas animation in IE6, 7 & 8 with FlashCanvas (Demo)

Slide 7

Slide 7 text

WebSocket API support with instant fallbacks to long polling using socket.io (Demo)

Slide 8

Slide 8 text

CSS3Pie - A polyfill for CSS3 decoration features

Slide 9

Slide 9 text

CSS3 border-radius,box-shadow and gradients in IE7

Slide 10

Slide 10 text

CSS3 patterns gallery for modern browsers (Demo)

Slide 11

Slide 11 text

Which we can polyfill for IE9 (Demo)

Slide 12

Slide 12 text

This is only the tip of the iceberg Imagine if we could polyfill things like.. In-browser speech detection (WebKit/Chrome) CSS Shaders (Chrome Canary) or even... ! ! !

Slide 13

Slide 13 text

WebCam access in special Opera/Chrome builds using getUserMedia() (Demo)

Slide 14

Slide 14 text

Features & Support

Slide 15

Slide 15 text

All of these features are now possible.. Media queries WebSockets Web Storage HTML5 video Web Workers Application cache WebGL and more!! but support is fragmented ! ! ! ! ! ! ! !

Slide 16

Slide 16 text

HTML5 & CSS3 Readiness (View)

Slide 17

Slide 17 text

Can I Use? (View)

Slide 18

Slide 18 text

oldIE: Internet Explorer 6, 7 & 8. aka, the three browsers often getting the low-res experience. — Paul Irish “ ”

Slide 19

Slide 19 text

Our biggest issue - browser support New features will never be available in oldIE. Media queries - IE9, 10 WebSockets - IE10 HTML5 video - IE9, 10 Web Workers - IE10 HTML5 History API - IE10 Application cache - IE10 WebGL - Unknown ! ! ! ! ! ! !

Slide 20

Slide 20 text

Unless you're using something like Chrome Frame

Slide 21

Slide 21 text

Hold on! Support isn't just an IE issue! Bleeding-edge features aren't available in all modern browsers at the same time. CSS Regions CSS Grid Layout CSS Filter Effects Web Audio API Page Visibility API ContextMenu API Download API ! ! ! ! ! ! !

Slide 22

Slide 22 text

Can we use modern features now? Let's wait...or

Slide 23

Slide 23 text

Use Polyfills & Shims

Slide 24

Slide 24 text

Polyfills are a type of shim that retrofit legacy browsers with modern HTML5/CSS3 features — Remy Sharp “ ”

Slide 25

Slide 25 text

Shims refer to any code that intercepts API calls and provides a layer of abstraction — Paul Irish “ ”

Slide 26

Slide 26 text

What can they do? Polyfills help us use today's modern features in yesterday's browsers Use native capabilities if a browser does support a feature Use fallbacks (Java applets, Flash, JS) for browsers that don't Provide as consistent an experience as is possible* *More on this later! ! ! ! !

Slide 27

Slide 27 text

What polyfills are widely used today? HTML5Shim/HTML5Shiv respond.js mediaelement.js socket.io flashcanvas store.js / AmplifyJS CSS3Pie history.js/pjax ! ! ! ! ! ! ! !

Slide 28

Slide 28 text

No content

Slide 29

Slide 29 text

No content

Slide 30

Slide 30 text

Modernizr - feature detection made simple Adds classes to the html tag based on browser capabilities This enables styling rules that can only be rendered in capable browsers .no-cssgradients .shinybutton { background: url("shinybutton.jpg"); } .cssgradients .shinybutton { background-image: linear-gradient(top, #555, #333); } ! !

Slide 31

Slide 31 text

Modernizr feature-detection tests Tests for many features come readily built-in (hot) Does the browser support WebGL? if (Modernizr.webgl){ loadAllWebGLScripts(); // webgl assets can easily be > 300k } else { var msg = 'WebGL is not available in your browser'; document.getElementById( '#notice' ).innerHTML = msg; } We'll look at more Modernizr feature detection tests later. ! !

Slide 32

Slide 32 text

READ THE DOCS FOR MORE ON BUILT-IN TESTS

Slide 33

Slide 33 text

Modernizr also supports custom feature detection plug-ins WebAudio API Modernizr.addTest('webaudio', !!(window.webkitAudioContext || window.AudioContext)); Track API Modernizr.addTest('trackapi', typeof document.createElement('video').addTextTrack === 'function');

Slide 34

Slide 34 text

Include HTML5Shim & we can also enable styling and using semantic HTML5 elements in oldIE All browsers have a master list of elements supported If an element isn't on this list it's considered unknown How should these elements be styled? ! ! !

Slide 35

Slide 35 text

More issues oldIE doesn't allow these elements to be styled at all What does the DOM for an unknown element look like? 1. IE inserts it as a empty node without any children 2. Children of the element are treated as siblings ! ! ! ! !

Slide 36

Slide 36 text

The solution Create a dummy element in the page before using it Don't even need to insert it into the DOM! article { border:1px solid red; display:block} document.createElement('article');

Hello FITC!

... ! !

Slide 37

Slide 37 text

So, HTML5Shim.. Runs a little loop in JavaScript to 'enable' all the different elements in HTML5 Allows us to style tags like instead of
in older browsers

I can now be styled in all browsers!

Remember, polyfills still needed for other features ! !

Slide 38

Slide 38 text

Issues & Solutions

Slide 39

Slide 39 text

It's important to remember.. Just because you can load a polyfill doesn't mean you should The fastest loading page on the planet is this Each thing added to this page means more time the browser has to spend loading or processing Consider performance - developers don't benchmark polyfills enough (more on this soon!) Look at speed, value added, loading mechanism ! ! ! ! !

Slide 40

Slide 40 text

Take the 'hardboiled' approach

Slide 41

Slide 41 text

It's okay for users to get different experiences

Slide 42

Slide 42 text

Lo-res - users are still delivered content. Default stylesheet used instead.

Slide 43

Slide 43 text

Be a champion of performance

Slide 44

Slide 44 text

Optimize to make best use of the capabilities a user's browser supports

Slide 45

Slide 45 text

Only load polyfills if they're absolutely needed There are some great script loaders that can help with conditional loading yepnope.js (standalone, Modernizr) - Alex Sexton LabJS - Kyle Simpson YeahNo.js - also by Kyle ! ! !

Slide 46

Slide 46 text

No content

Slide 47

Slide 47 text

yepnope.js - an asynchronous conditional resource loader Example: conditionally load a geolocation polyfill and stylesheet yepnope({ test: Modernizr.geolocation, yep: 'regular-styles.css', nope: ['modified-styles.css', 'geolocation-polyfill.js'], callback: function (url, result, key) { if (url === 'modified-styles.css') { alert("woohoo! it's loaded"); } } });

Slide 48

Slide 48 text

Modernizr includes yepnope.js in special builds Supports similarly loading up a geolocation polyfill depending on support Modernizr.load({ test: Modernizr.geolocation, yep : 'geo.js', nope: 'geo-polyfill.js' });

Slide 49

Slide 49 text

No content

Slide 50

Slide 50 text

LabJS Example: conditionally load a JSON polyfill if it isn't natively supported $LAB.script(function(){ if (typeof JSON == "undefined") return "json2.js"; }) .wait() .script("myotherscript.js"); An alternative: $LAB.script(typeof JSON == "undefined" ? "json2.js" : false).wait() .script("myotherscript.js");

Slide 51

Slide 51 text

YeahNo.js - a yepnope API wrapper around LabJS Example: conditionally load a geolocation polyfill and stylesheet yepnope({ test: Modernizr.geolocation, yep: 'regular-styles.css', nope: ['modified-styles.css', 'geolocation-polyfill.js'], callback: function (url, result, key) { if (url === 'modified-styles.css') { alert('The Styles loaded!'); } } });

Slide 52

Slide 52 text

Writing Polyfills

Slide 53

Slide 53 text

Writing Polyfills Why should you give writing polyfills a go? Use modern/bleeding-edge features in today's browsers Fantastic opportunity to learn subtleties in vendor implementations It'll force you to read specifications and understand them If it's reliable, other developers may also be able to use it ! ! ! !

Slide 54

Slide 54 text

Test what features your current browser supports (View)

Slide 55

Slide 55 text

Does Browser-x natively support the feature? Browser.next?

Slide 56

Slide 56 text

Specifications - What does the API look Like? Check standards groups like the W3C for specs

Slide 57

Slide 57 text

Quirks - What quirks do older browser implementations suffer from? QuirksMode.org

Slide 58

Slide 58 text

You can't detect 'HTML5 Support', but you can detect support for individual features — Mark Pilgrim “ ”

Slide 59

Slide 59 text

Feature detection has some friends There are some useful tips to keep in mind Objects like window and document are your friend Fire up the console and look at this: window //explore me! BOOM. Often the first place to check for support of new features Careful. Not all browsers have the same naming conventions for experimental features ! ! ! !

Slide 60

Slide 60 text

Testing techniques in order of preference: 1. Feature testing - check for the existence of a method and if it returns the correct output 2. Feature detection - check for the existence of a method 3. Weak inference - check for the existence of an unrelated method 4. UA sniffing - check the browser's user agent string Thanks to @mathias and @jdalton for this list More on these very soon! ! ! ! !

Slide 61

Slide 61 text

Support Detecting finalized and unfinalized features. Test if: 1. Property of the feature exists on a global object (window or navigator) 2. Property of the feature exists on a specific element 3. Method of the feature exists on a specific element where the value it returns can be tested 4. Property of the feature can be set and its value retained ! ! ! !

Slide 62

Slide 62 text

1. Property exists on a global object Testing for geolocation support function isGeolocationSupported(){ return !!navigator.geolocation; } and with Modernizr it's as simple as.. if(Modernizr.geolocation){ // supported }else{ // not supported }

Slide 63

Slide 63 text

2. Property of the feature exists on a specific element Testing for support function isCanvasSupported(){ return !!document.createElement('canvas').getContext; } and with Modernizr its.. if(Modernizr.canvas){ // supported }else{ // not supported }

Slide 64

Slide 64 text

3. Method of the feature exists on a specific element where the value it returns can be tested Testing for support function isAudioSupported(){ return !!document.createElement('audio').canPlayType; } and with Modernizr its.. if(Modernizr.audio){ // supported }else{ // not supported }

Slide 65

Slide 65 text

But we can take this further Testing for format support if(isAudioSupported()){ var audio = document.createElement('audio'); if(audio.canPlayType('audio/mpeg')=='probably'){ //supports MP3 audio audio.src = 'music.mp3'; } else if(audio.canPlayType('video/ogg; codecs="theora"')=='probably'){ //supports Ogg/Vorbis audio audio.src = 'music.ogg'; } }else{ //load a flash fallback }

Slide 66

Slide 66 text

and with Modernizr its.. if(Modernizr.audio){ var audio = new Audio(); //If Ogg is supported, load 'music.ogg' //Otherwise the MP3 or M4A fallback depending //on browser support audio.src = Modernizr.audio.ogg ? 'music.ogg' : Modernizr.audio.mp3 ? 'music.mp3' : 'music.m4a'; }else{ //use a flash fallback }

Slide 67

Slide 67 text

4. Property of the feature can be set and it's value retained Testing for support function isColorPickerSupported(){ var input = document.createElement('input'); input.setAttribute('type','color'); return input.type !== 'text'; } and with Modernizr its.. if(Modernizr.inputtypes.color){ // supported }else{ // not supported

Slide 68

Slide 68 text

More Feature-Detection Tests Very, very simple JavaScript API support

Slide 69

Slide 69 text

Very, very simple JavaScript API support testing function isAPISupported(api, source){ //return (api in source) or.. return !!source[api]; }; // testing with google chrome isAPISupported('geolocation', navigator); // true isAPISupported('pushState', history); // true isAPISupported('localStorage', window); // true isAPISupported('sessionStorage', window); // true Note: If a third-party library is extending host objects, 'a' in b or b.a testing may provide unreliable results. Keep in mind other scripts on Simple CSS property support testing

Slide 70

Slide 70 text

Simple CSS property support testing function isPropSupported(prop){ var el = document.createElement('div'); return prop in el.style; }; isPropSupported('borderRadius'); // true isPropSupported('boxShadow'); // true isPropSupported('textShadow'); // true Simple CSS selector support testing

Slide 71

Slide 71 text

Simple CSS selector support testing function isSelectorSupported(sel){ var el = document.createElement('div'); el.innerHTML = '​'+ sel + '{}'; document.body.appendChild(el); return !!el.lastChild.sheet.cssRules[0]; }; isSelectorSupported('::first-child'); // true isSelectorSupported('::after'); // true isSelectorSupported('::before'); // true isSelectorSupported(':nth-child(even)'); // true Basic HTML Attribute support testing

Slide 72

Slide 72 text

Basic HTML Attribute support testing function isAttribSupported(prop, el){ var el = document.createElement(el); return prop in el; } // Some simple HTML5 feature-detection tests isAttribSupported('placeholder', 'input'); // true isAttribSupported('play', 'video'); // true isAttribSupported('pause', 'audio'); // true isAttribSupported('getContext', 'canvas'); // true Going further: snippets from has.js

Slide 73

Slide 73 text

Going further: snippets from has.js HTML5 audio feature test for WAV var audio = document.createElement('audio'); audio.canPlayType("audio/wav; codecs=1"); //probably CSS3 support detection (border radius) var elStyle = document.createElement('div').style; if(typeof elStyle['borderRadius']=="string"){ //supported } Modernizr snippets

Slide 74

Slide 74 text

Modernizr snippets File API: Where a spec includes multiple features !!(window.File && window.FileList && window.FileReader) Data URI Support var dataURI = new Image(); datauri.onload = function(){ return (datauri.width == 1 && datauri.height == 1); // true or false } datauri.src='data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==';

Slide 75

Slide 75 text

Asynchronous Example: WebP (lossless image format) (function(){ // full version: http://bit.ly/qLJbFj var image = new Image(); image.onerror = function() { Modernizr.addTest('webp', false); }; image.onload = function() { Modernizr.addTest('webp', function() { return image.width == 1; }); }; image.src = 'data:image/webp;base64,UklGRj..'; }());

Slide 76

Slide 76 text

Vendor prefixes Allow vendors to implement experimental features before they've been finalized // From css3please.com: .box_transition { -webkit-transition: all 0.3s ease-out; /* Saf3.2+, Chrome */ -moz-transition: all 0.3s ease-out; /* FF4+ */ -ms-transition: all 0.3s ease-out; /* IE10? */ -o-transition: all 0.3s ease-out; /* Opera 10.5+ */ transition: all 0.3s ease-out; /*fast-forward compatible*/ } Edge-features occasionally need to be tested prepending a vendor prefix to the feature name.

Slide 77

Slide 77 text

CSS3 Please - The Cross-Browser Rule Generator (View)

Slide 78

Slide 78 text

Getting the vendor prefix function getPrefix(prop){ var prefixes = ['Moz','Khtml','Webkit','O','ms'], elem = document.createElement('div'), upper = prop.charAt(0).toUpperCase() + prop.slice(1); if (prop in elem.style) return prop; for (var len = prefixes.length; len--; ){ if ((prefixes[len] + upper) in elem.style) return (prefixes[len] + upper); } return false; } console.log(getPrefix('transform'));//WebkitTransform

Slide 79

Slide 79 text

Getting the vendor prefix with Modernizr console.log(Modernizr.prefixed('transform'));//WebkitTransform

Slide 80

Slide 80 text

Polyfills with jQuery

Slide 81

Slide 81 text

A very very simple jQuery placeholder polyfill The HTML5 Placeholder attribute is used as follows: Begin by iterating over all the input elements with a placeholder attribute $("input[placeholder]").each(function() { // more logic to come! }); Please enter some text

Slide 82

Slide 82 text

Step 2 Get the value of the placeholder attribute, remove default placeholder: $("input[placeholder]").each(function() { var $e = $(this), placeholder = $e.attr("placeholder"); $e.removeAttr("placeholder").val(placeholder); // A little more left to go });

Slide 83

Slide 83 text

Step 3 Polyfill the placeholder text behavior to be cross- browser: $("input[placeholder]").each(function() { var $e = $(this), placeholder = $e.attr("placeholder"); $e.removeAttr("placeholder").val(placeholder); $e.bind("focus blur", function(e) { if (e.type === "focus" && $e.val() === placeholder) { $e.val(""); } else { if (!$e.val()) { $e.val(placeholder); } } }); });

Slide 84

Slide 84 text

Some quick notes This was a quick example and the code didn't account for password inputs, textareas or values of 'placeholder' entered It will also submit the placeholder values if no value is entered. Ideally use this awesome plugin by @mathias instead ! ! !

Slide 85

Slide 85 text

Watch out! Not everything can be detected (View)

Slide 86

Slide 86 text

Performance

Slide 87

Slide 87 text

Benchmark performance of the complete polyfill Are there other scripts loading on the page? Polyfills relying on other polyfills? ! ! !

Slide 88

Slide 88 text

Break your polyfill into smaller parts. Can those be tested or optimized further?

Slide 89

Slide 89 text

Is the polyfill visibly slow in some browsers? Use vs. lose

Slide 90

Slide 90 text

Benchmark performance with jsPerf.com (View)

Slide 91

Slide 91 text

Case study: forEach() (ES5)

Slide 92

Slide 92 text

Performance testing involved.. Discovering how well the native feature performed Benchmarking how well various polyfills for it performed Deciding which browsers to use it in based on this information ! ! !

Slide 93

Slide 93 text

No content

Slide 94

Slide 94 text

Getting the polyfill out there

Slide 95

Slide 95 text

Distribution check-list Before you release your polyfill into the wild.. Unit tests - do your best to include them if possible Documentation - what does and doesn't it do? Support - level of future-support and maintenance Alternatives - acknowledge, describe differences. help users (Optional, but nice) Performance tests ! ! ! ! !

Slide 96

Slide 96 text

Offer minified versions of your polyfill

Slide 97

Slide 97 text

Host on GitHub

Slide 98

Slide 98 text

Post To The Modernizr Polyfills Wiki

Slide 99

Slide 99 text

The Future

Slide 100

Slide 100 text

Polyfills will probably still exist in the future.

Slide 101

Slide 101 text

Will they be around forever? As browser vendors implement new specs and features, the need for specific polyfills will decrease. There will be a day when oldIE is dead but polyfills will still come in useful for filling missing gaps in other browsers Until then, regularly test latest browsers in between releases to ensure the polyfill isn't loading unless needed ! !

Slide 102

Slide 102 text

Firefox nightlies

Slide 103

Slide 103 text

Chromium (Stable, Beta, Canary builds)

Slide 104

Slide 104 text

Opera.next

Slide 105

Slide 105 text

Internet Explorer Preview

Slide 106

Slide 106 text

SUMMARY What did we learn today? Polyfills are amazing when used responsibly Writing your own polyfills or feature detection tests isn't as hard as it looks Don't be afraid to give users a lower-res experience where it makes sense Benchmark what you do to ensure users are given the fastest experience possible ! ! ! !

Slide 107

Slide 107 text

That's a wrap! For more on me: @addyosmani http://addyosmani.com http://github.com/addyosmani G+:Addy Osmani Big thanks to @paul_irish, @mathias, @peol, @rem and others for their previous work in this area and technical reviews. ! ! ! !