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.
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 }
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"
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/
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, ... ...
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.”
→ "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.
side effects when required capabilities aren't present Degrades gracefully If enhancements aren't atomic, bad things happen. Broken layouts Javascript errors Unusable interfaces
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 ' ) ; . . .
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 ) }
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 . . . '
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 }
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 }
functionality: "polyfilling" Can be network and processor intensive, rarely an exact match Alternative functionality: "sandwich filling" Usually unnecessary…
( 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 * / }
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 ; } ) ;
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 ' } ) ;
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
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
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
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 } ) ;
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 } ) ;