Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Compatibility via Modernizr

Stu Cox
June 27, 2013

Compatibility via Modernizr

My talk at McrFRED (http://fredup.github.io/manchester/), June 2013.

Stu Cox

June 27, 2013
Tweet

More Decks by Stu Cox

Other Decks in Technology

Transcript

  1. Compatibility via Modernizr Making web things fit their medium by

    / #McrFRED | 27th June 2013 | Manchester, UK Stu Cox @stucoxmedia
  2. In this case: Your web thing ←→ Your user's browser/device

    com•pat•i•bil•i•ty |kәmˌpatɪˈbɪlɪti| (abbr.: compat.) noun (pl. -i•ties) a state in which two things are able to exist or occur together without problems or conflict.
  3. 1. Make a 2. Test it in Browser A 3.

    It works! Hurray! web thing
  4. So we hack it. CSS hacks: User-Agent sniffs: These are

    essentially heuristics. . b t n { * m a r g i n - l e f t : - 1 3 p x ; } i f ( n a v i g a t o r . u s e r A g e n t . m a t c h ( / M S I E [ 6 7 ] \ . / ) ) { / / F i x f o r o l d I E }
  5. Heuristics imply assumptions. "All browsers which parse CSS hack A

    also have layout bug B" "All browsers which match user-agent C support feature D" "I know about every browser my users might use" "If my assumptions are true now, they'll also be true in the future"
  6. "I know about every browser my users might use" 85

    browser versions with > 0.1% market share 7,000 different devices login to Facebook every day [1] Users have different needs (think accessibility) [1] techcrunch.com/2012/08/03/vp-mike-schroepfer-7000-different-mobile-devices-access-facebook-every-day/
  7. Features CSS: @ f o n t - f a

    c e , transitions, animations, flexbox, ... HTML: < a u d i o > , < v i d e o > , input types, drag & drop, ... JavaScript: History API, IndexedDB, WebSockets, ... ...
  8. Features are capabilities "Browser X has the ability to render

    SVG" Plugins add capabilities "A browser with the Flash plugin has the ability to render Flash media" Bugs are incapabilities "Browser Y has the ability NOT to fuck up the box model" “The differences between 2 users' browsers can be described (entirely) by the differences between their capability sets.”
  9. Progressive Enhancement It was going to get mentioned sooner or

    later. Providing different experiences for different users, depending on their capabilities.
  10. Think of your web thing as a collection of features.

    Core: the essential bits every user needs Enhancements: non-essential additions The core is smaller than you think.
  11. Each feature depends on capabilities of the browser. Core capabilities

    → "system requirements" for your web thing Fewer core capabilities = accessible to more users. Enhancement capabilities → tiers of experience If a user has the required capabilities, they get the enhancement; otherwise they don't.
  12. What's an enhancement? Examples: Some styling Fonts Animations Audio /

    video content A background image A whole functional part – e.g. a chat feature
  13. Atomic Enhancements Either applied fully, or not at all No

    side effects when required capabilities aren't present Degrades gracefully If enhancements aren't atomic, bad things happen. Broken layouts Javascript errors Unusable interfaces
  14. Examples: If b o x - s i z i

    n g not supported, layout won't be as expected. TypeError: Object #<HTMLDocument> has no method 'querySelectorAll' . m o d u l e { b o x - s i z i n g : b o r d e r - b o x ; p a d d i n g : 1 e m ; w i d t h : 2 0 e m ; } / / M y m o d u l e v a r m o d u l e s = d o c u m e n t . q u e r y S e l e c t o r A l l ( ' . m o d u l e ' ) ; . . .
  15. How can we ensure enhancements are atomic? 1. Avoid certain

    dependencies 2. Safety net 3. Feature detect
  16. Basic pattern i f ( s u p p o

    r t s F e a t u r e ) { / / U s e f e a t u r e ! / / E n s u r e a l l c o d e d e p e n d i n g o n t h i s f e a t u r e i s / / c o n t a i n e d h e r e . . . n o s i d e e f f e c t s ! } e l s e { / / S o m e f a l l b a c k ( o p t i o n a l ) }
  17. Techniques 1. Does it exist? 2. Does it stick? 3.

    Does it work? ' g e o l o c a t i o n ' i n n a v i g a t o r v a r e l = c r e a t e E l e m e n t ( ' d i v ' ) ; e l . s t y l e . c s s T e x t = ' f i l t e r : b l u r ( 2 p x ) ' ; ! ! e l . s t y l e . l e n g t h / / t r u e i f C S S f i l t e r s s u p p o r t e d v a r i m a g e = n e w I m a g e ( ) ; i m a g e . o n l o a d = f u n c t i o n ( ) { i m a g e . w i d t h = = 1 / / t r u e i f W e b P s u p p o r t e d } i m a g e . s r c = ' d a t a : i m a g e / w e b p ; b a s e 6 4 , U k l G R i w A A A B X R U J Q V l A 4 I . . . '
  18. Media Queries Yep, they're a kind of feature detection too.

    In CSS: In JS: @ m e d i a ( m i n - w i d t h : 8 0 0 p x ) { / / H a s a l a r g e v i e w p o r t } @ m e d i a n o t ( m i n - w i d t h : 8 0 0 p x ) { / / D o e s n ' t h a v e a l a r g e v i e w p o r t } i f ( w i n d o w . m a t c h M e d i a ( ' ( m i n - w i d t h : 8 0 0 p x ) ' ) . m a t c h e s ) { / / H a s a l a r g e v i e w p o r t } e l s e { / / D o e s n ' t h a v e a l a r g e v i e w p o r t }
  19. Native Detection Via @ s u p p o r

    t s In CSS: In JS: @ s u p p o r t s ( d i s p l a y : f l e x ) { / / S u p p o r t s f l e x b o x } @ s u p p o r t s n o t ( d i s p l a y : f l e x ) { / / D o e s n ' t s u p p o r t f l e x b o x } i f ( w i n d o w . C S S . s u p p o r t s ( ' d i s p l a y ' , ' f l e x ' ) { / / S u p p o r t s f l e x b o x } e l s e { / / D o e s n ' t s u p p o r t f l e x b o x }
  20. Fallbacks No fallback: "feature gating" Efficient, easy to maintain. Replace

    functionality: "polyfilling" Can be network and processor intensive, rarely an exact match Alternative functionality: "sandwich filling" Usually unnecessary…
  21. Basic patterns It makes feature detection a breeze i f

    ( M o d e r n i z r . g e o l o c a t i o n ) { / / U s e f e a t u r e ! / / E n s u r e a l l c o d e d e p e n d i n g o n t h i s f e a t u r e i s / / c o n t a i n e d h e r e . . . n o s i d e e f f e c t s ! } e l s e { / / S o m e f a l l b a c k ( o p t i o n a l ) } . g e o l o c a t i o n . m o d u l e { / * S t y l e s i f g e o l o c a t i o n s u p p o r t e d * / } . n o - g e o l o c a t i o n . m o d u l e { / * S t y l e s i f g e o l o c a t i o n n o t s u p p o r t e d * / }
  22. Roll your own Via M o d e r n

    i z r . a d d T e s t ( ) M o d e r n i z r . a d d T e s t ( ' y o d a ' , f u n c t i o n ( ) { v a r y o d a = d o c u m e n t . c r e a t e E l e m e n t ( ' y o d a ' ) ; r e t u r n ' t h e f o r c e ' i n y o d a ; } ) ;
  23. Conditional Loading Via M o d e r n i

    z r . l o a d ( ) Avoid heavy loading for browsers which can't use it Rarely need n o p e – big polyfills are a bad idea! M o d e r n i z r . l o a d ( { t e s t : M o d e r n i z r . g e o l o c a t i o n , y e p : ' g e o . j s ' , n o p e : ' g e o - p o l y f i l l . j s ' } ) ;
  24. Modernizr v3.0 New AMD-based internal architecture Builds are waaaaay smaller

    20+ more detects since 2.6.2 Better handling of async tests Uses @ s u p p o r t s under the hood Faster release cycle Better documentation Easier integration with Coming soon, we promise! See: grunt-modernizr Alex Sexton's Modernizr 3 Workflow
  25. A good feature detect... Gives accurate positives Gives accurate negatives

    Is lightweight (fast & small) Doesn't make assumptions or use heuristics Realistically, most detects make some assumptions – we try to minimise these
  26. Rule 1: It must interact with the document Because that's

    all we can access from JS. Styling Can't access the pixels on the screen Best-guess based on the (re)actions of the DOM Form UIs Appear on top of the document – invisible to us
  27. Rule 2: It shouldn't take any user interaction Events Can't

    tell if events (e.g. D O M C o n t e n t L o a d e d ) will be fired at the correct time c o n t e n t e d i t a b l e We can often give accurate negatives, but not positives
  28. Rule 3: Think about older browsers/devices Using new APIs e.g.

    w i n d o w . p e r f o r m a n c e – tells us nothing about older devices Touchscreens Don't get me started...
  29. You can't detect a touchscreen Not reliably, anyway All techniques

    either use heuristics or rely on new APIs. http://stucox.com/blog/you-cant-detect-a-touchscreen/
  30. In fact, you can't detect many device features Not reliably,

    anyway Think about the assumptions you're making
  31. Idea: modular capability dependencies RequireJS-like syntax for defining browser dependencies

    b r o w s e r R e q u i r e ( [ ' s v g ' , ' c a n v a s ' ] , f u n c t i o n ( ) { / / O n l y r u n s i f c a p a b i l i t i e s a v a i l a b l e } ) ;
  32. Even better: a RequireJS plugin r e q u i

    r e ( [ ' j q u e r y ' , ' M ! s v g ' , ' M ! c a n v a s ' ] , f u n c t i o n ( $ ) { / / O n l y r u n s i f s o f t w a r e A N D c a p a b i l i t y d e p e n d e n c i e s / / s a t i s f i e d } ) ;