MEDIA QUERIES
 Mobile Elixir or CSS Snake Oil?
      james williamson | lynda.com
Howdy y’all
  james williamson

                   | senior author


     man-about-town

   @jameswillweb on the Twitter
Let’s Take Your Temperature...
Global mobile internet usage | 2003
Global mobile internet usage | 2011
Why do designers fear the mobile web?




        Because we’ve only just now
            gotten this to work
...and now we have to deal with this




             (images not to scale)
Past options for developing for the mobile web

          Build a separate mobile site.


          Hire a developer to build an app for you.



          Pray.
Surely there must be another option


                      CSS
               MEDIA
               QUERIES
               R
                Reflows content automatically, with no
               cramping or bloating. Works overnight, a
                  soothing balm for your mobile ills




        Good for what ails you?
So, what’s a media query?

CSS Media Queries give us a way to
 control the application of styles
based on the presence or absence
    of specific media features
The concept isn’t exactly new...


link	
  rel="stylesheet"	
  href="desktop.css"	
  media="screen"


                                                    look familiar?
However, we can now apply a little logic...


      link	
  rel="stylesheet"	
  href="desktop.css"	
  
      media="screen	
  and	
  (min-­‐width:500px)"


                                       that narrows it down a bit.
Media Query syntax
  Media Queries are logical expressions, they are either
“true” or “false” depending upon how they are evaluated. If
   true, the styles are applied, if false, they are ignored.




       link	
  rel="stylesheet"	
  href="desktop.css"	
  
       media="screen	
  and	
  (min-­‐width:500px)"


  In this example, the styles would only be applied if the UA supported the
           screen media type, and the display was at least 500px
Media Query syntax

    link	
  rel="stylesheet"	
  href="desktop.css"	
  
media="[not	
  |	
  only	
  ]	
  screen	
  [and]	
  (expression)"




            The keywords “not”, “only”, and “and” can be
           used to filter results, while expressions can be
             used to check for specific media features
Media Query syntax
  Logical operator “and” constrains a query based on the
expression that follows it. There is no “or” operator, normal
               comma-separated lists serve as “or.”


       link	
  rel="stylesheet"	
  href="desktop.css"	
  
       media="screen	
  and	
  (min-­‐width:500px)"

 Styles are applied for screen devices that have a width of 500px or greater




   link	
  rel="stylesheet"	
  href="desktop.css"	
  
   media="screen	
  and	
  (min-­‐width:500px),	
  projection	
  and	
  (color)"



          Styles are applied for screen devices that have a width of
                 500px or greater, or color projection devices
Media Query syntax
Logical operator “not” negates the results of the media query
and applies the styles if the conditions are NOT met. It negates
   the entire expression, not just media type. Use carefully.




       link	
  rel="stylesheet"	
  href="desktop.css"	
  
       media="not	
  screen	
  and	
  (min-­‐width:500px)"



      Styles are applied if the device is not a screen device with a width
       above 499px. This also means that styles WOULD be applied for
       screen devices with widths below 500px and other media types.
Media Query syntax
Logical operator “only” serves to hide style sheets from
older or non-conforming user agents. Conforming user
          agents are instructed to ignore “only.”




    link	
  rel="stylesheet"	
  href="desktop.css"	
  
    media="only	
  screen	
  and	
  (min-­‐width:500px)"



 Would be ignored by non-conforming agents. Other user agents would
    apply the styles to screen devices with widths 500px and above.
Media Query syntax

Media Features
width                     color
height                    color-­‐index
device-­‐width            monochrome
device-­‐height           resolution
orientation               scan
aspect-­‐ratio            grid
device-­‐aspect-­‐ratio
Media Query syntax

Media Feature values

length     width:500px


keyword    orientation:	
  landscape	
  |	
  portrait

ratio      aspect-­‐ratio:	
  16/9

integer    color:8
Media Query syntax

Media Feature prefixes

In many cases, you can use the “min-” and “max-”
prefixes to set less-than or greater-than ranges
for your values


                   width
                   min-­‐width
                   max-­‐width
Media Query syntax

Be careful!

         width	
  !=	
  device-­‐width


   (Honestly, even device-width != device width, or as
           PPK said, “a pixel is not a pixel*”)




           *http://www.quirksmode.org/blog/archives/2010/04/a_pixel_is_not.html
Enough syntax!
Let’s see it in action!




   Visit mediaqueri.es for a gallery of sites using media queries
Oh snap! That changes everything!

Except that it doesn’t.

We still need to talk about how media queries
work in the real world.
“Media queries are fools gold...”
                                           - Jason Grigsby*

So what’s his beef?


    Support for media queries isn’t that good




           *http://www.cloudfour.com/css-media-query-for-mobile-is-fools-gold/
“Media queries are fools gold...”
                                           - Jason Grigsby*

So what’s his beef?


   Having browsers scale images is a bad idea




           *http://www.cloudfour.com/css-media-query-for-mobile-is-fools-gold/
“Media queries are fools gold...”
                                          - Jason Grigsby*

So what’s his beef?


      Unnecessary resource downloading




          *http://www.cloudfour.com/css-media-query-for-mobile-is-fools-gold/
“Media queries are fools gold...”
                                          - Jason Grigsby*

So what’s his beef?


    Hiding elements doesn’t lower overhead




          *http://www.cloudfour.com/css-media-query-for-mobile-is-fools-gold/
“Media queries are fools gold...”
                                          - Jason Grigsby*

So what’s his beef?


    Media queries ignore the mobile context




          *http://www.cloudfour.com/css-media-query-for-mobile-is-fools-gold/
Browser Support
Browser                     Layout Engine           MQ support
Firefox                     Gecko                      3.6+
Google	
  Chrome            WebKit                     10+
Safari                      WebKit                     3.2+
Opera                       Presto                     11+
Internet	
  Explorer        Trident                    9+
iOS	
  Safari               WebKit                     3.2
Opera	
  Mini               Presto                     5.0
Opera	
  Mobile             Presto                     10.0
Android	
  Browser	
        Android	
  WebKit	
        2.1
Nokia                       multiple                   s40
Blackberry	
  Browser       Mango/WebKit               4.7.1
Samsung                     Android	
  WebKit          ???
OpenWave                    ???
UC	
  Web                   proprietary
NetFront                    NetFront
Palm                        WebKit                     WebOS	
  1.4
Another big problem...it doesn’t just...work
  For mobile, media queries are typically used to check for screen
      size. They do not perform browser or device sniffing. The
   multitude of different screen sizes, resolutions, pixel densities,
    and default scaling preferences can cause serious problems
             with how media query-driven sites display.
Oh...so....I guess we can go now right?
                                     dang.




Not so fast. Media queries CAN work, and can be an important
part of your mobile development strategy... you just have to use
   them correctly, and combine them with other techniques
Let’s talk strategy




                Mobile First*
Popularized by Luke Wroblewski, it emphasizes
starting the design process with mobile in mind.



                            *http://www.lukew.com/presos/preso.asp?26
Mobile first media queries
In terms of media queries, mobile first means starting
with your mobile styles, and then enhancing designs
      for other screen sizes including desktop.
Now, about media query support...
             Respond.js from the Filament Group
                  https://github.com/scottjehl/Respond
                  (gzipped version is 1kb)



             css3-mediaqueries-js by Wouter van der Graaf
                  http://code.google.com/p/css3-mediaqueries-js/
                  (15kb uncompressed)



A mobile-first strategy makes using these libraries critical.
Now, let’s tame the viewport!


            CSS
     MEDIA
     QUERIES
                                                +   VIEWPORT
     R
      Reflows content automatically, with no
     cramping or bloating. Works overnight, a
        soothing balm for your mobile ills
                                                    Controls scaling and resolution with no
                                                      bloating, dizzyness, or unpleasant
                                                      aftertaste. A true joy for the home.




   = feel better by morning!
Meta Viewport tags

Meta viewport tags can be combined with media
queries to help ensure consistent experiences.



  <meta	
  name="viewport"	
  content="width=device-­‐width,	
  
  initial-­‐scale=1.0">


                                   what’s this all about then?
So what can meta viewport tags do?

    Meta Viewport properties

     width	
  =	
  [pixel	
  |	
  device-­‐width	
  ]
     height	
  =	
  [pixel	
  |	
  device-­‐height	
  ]



You can set width and height to explicit pixel values, or set
them to device width and height, which instruct the device
   to set the viewport width to the device screen width
So what can meta viewport tags do?

   Meta Viewport properties

    initial-­‐scale	
  =	
  0*	
  -­‐	
  10
    minimum-­‐scale	
  =	
  0*	
  -­‐	
  10
    maximum-­‐scale	
  =	
  0*	
  -­‐	
  10


These values allow you to control the initial scaling of the
page (to control whether your page is initially zoomed out
or not), and the minimum and maximum scaling allowed.


                                              * Android minimum is 0.01
So what can meta viewport tags do?

   Meta Viewport properties

    user-­‐scalable	
  =	
  [	
  yes	
  |	
  no	
  ]



Controls whether or not the user can change the scale of
  the page. If the value is set to no, any previously set
  minimum and maximum scaling values are ignored.
So what can meta viewport tags do?

     Meta Viewport properties

       target-­‐densitydpi	
  =	
  [	
  dpi_value	
  |	
  device-­‐dpi	
  
       |	
  high-­‐dpi	
  |	
  medium-­‐dpi	
  |	
  low-­‐dpi	
  ]	
  ]



Android Only: Allows you to target screen resolution. You can target a dpi
value (70 - 400), the device dpi (prevents default scaling), or you can target
one of three Android screen density categories. Content will then scale up
 or down if the resolution doesn’t match the target density. Essentially, it
     allows you to control how CSS pixels are scaled to device pixels.


     *For WebKit, you can use (-webkit-min-device-pixel-ratio: 2) to target higher density displays
Let’s look at that again...

    <meta	
  name="viewport"	
  content="width=device-­‐width,	
  
    initial-­‐scale=1.0">



This syntax tells the device to set the viewport width to the
actual device width to ensure the proper media query styles
      are used, and set the initial page scale to 100%.


  Never use media queries without a meta viewport tag.
                              Ever.
What about resource loading?

             OMG. I cannot believe
               I just ate all that!
The truth about media query loading...
      <link	
  rel="stylesheet"	
  href="desktop.css"	
  media="screen,	
  
      projection">


      <link	
  rel="stylesheet"	
  href="tablet.css"	
  media="all	
  and	
  
      (min-­‐width:	
  481px)	
  and	
  (max-­‐width:	
  768px)">


      <link	
  rel="stylesheet"	
  href="mobile.css"	
  media="all	
  and	
  
      (min-­‐width:	
  0px)	
  and	
  (max-­‐width:	
  480px)">




   This is very inefficient. All three CSS files will load,
regardless of which media styles are loaded. This creates
    additional HTTP requests with no added savings.
    Combine these files using inline @media syntax.
The truth about media query loading...
      #actionCall	
  {
      	
   display:	
  none;
      }




  This doesn’t help you either. If a widget or image is
present in the element, it is still downloaded, regardless
                   of the display property.
The truth about media query loading...
     @media	
  //mobile	
  {
     #actionCall	
  {
     	
   background:	
  none;
     	
  	
  }
     }
     @media	
  //desktop	
  {
     #actionCall	
  {
     	
   background:	
  url(big_ole_image.jpg);
     	
  	
  }
     }


   This is better. If the mobile property is set to no
background image, iOS does not download the desktop
 version. Sadly it seems that Android currently does.
How can we control resource loading?


     Modernizr 2 features both media query tests AND the
YepNope.js library. This allows you to combine feature detection,
    media query success, and conditional resource loading.



                          <BOOM>
                    http://www.modernizr.com/
How can we control resource loading?
Of course, if you prefer, you can roll your own. PPK reports in his
   own testing, document.documentElement.clientWidth and
  screen.width give the same results as the width and device-
      width media queries*. This means you could do this:


        if	
  (screen.width	
  >=	
  600)	
  {
        	
   //	
  load	
  resources
        }

        or
        if	
  (document.documentElement.clientWidth	
  >=	
  
        600)	
  {
        	
   //	
  load	
  resources
        }



                  *http://www.quirksmode.org/blog/archives/2010/08/combining_media.html
Media Query best practices
Design with mobile in mind first

Make the mobile styles your default styles and progress up

Use fluid layouts to deal with minor screen size differences

Combine CSS & JS files to reduce HTTP requests

Minimize and gzip compress your code

Use Data URL and CSS Sprites when you can

Don’t use external libraries unless you really need to

Consider using touch frameworks for interactivity
Looks like gold to me!



                       CSS
                MEDIA
                QUERIES
                R
                 Reflows content automatically, with no
                cramping or bloating. Works overnight, a
                   soothing balm for your mobile ills




(That? Oh, that’s just the halo of truth...)
So...where does that leave us?
Just like every other technique in your toolbox, media
queries simply add to your capabilities.


Are they right for every project? Of course not. Mobile
design is far more than simply designing for a smaller
screen.


However, given the right circumstances, media queries
allow you to optimize designs for the mobile environment
in a way that we weren’t able to do before.


Deciding when, and if, to use them is, after all, your job.
THANK YOU
james williamson | lynda.com
   jwilliamson@lynda.com
@jameswillweb on the Twitter
  www.simpleprimate.com

CSS3 Media Queries: Mobile Elixir or CSS Snake Oil

  • 1.
    MEDIA QUERIES MobileElixir or CSS Snake Oil? james williamson | lynda.com
  • 2.
    Howdy y’all james williamson | senior author man-about-town @jameswillweb on the Twitter
  • 3.
    Let’s Take YourTemperature...
  • 4.
  • 5.
  • 6.
    Why do designersfear the mobile web? Because we’ve only just now gotten this to work
  • 7.
    ...and now wehave to deal with this (images not to scale)
  • 8.
    Past options fordeveloping for the mobile web Build a separate mobile site. Hire a developer to build an app for you. Pray.
  • 9.
    Surely there mustbe another option CSS MEDIA QUERIES R Reflows content automatically, with no cramping or bloating. Works overnight, a soothing balm for your mobile ills Good for what ails you?
  • 10.
    So, what’s amedia query? CSS Media Queries give us a way to control the application of styles based on the presence or absence of specific media features
  • 11.
    The concept isn’texactly new... link  rel="stylesheet"  href="desktop.css"  media="screen" look familiar?
  • 12.
    However, we cannow apply a little logic... link  rel="stylesheet"  href="desktop.css"   media="screen  and  (min-­‐width:500px)" that narrows it down a bit.
  • 13.
    Media Query syntax Media Queries are logical expressions, they are either “true” or “false” depending upon how they are evaluated. If true, the styles are applied, if false, they are ignored. link  rel="stylesheet"  href="desktop.css"   media="screen  and  (min-­‐width:500px)" In this example, the styles would only be applied if the UA supported the screen media type, and the display was at least 500px
  • 14.
    Media Query syntax link  rel="stylesheet"  href="desktop.css"   media="[not  |  only  ]  screen  [and]  (expression)" The keywords “not”, “only”, and “and” can be used to filter results, while expressions can be used to check for specific media features
  • 15.
    Media Query syntax Logical operator “and” constrains a query based on the expression that follows it. There is no “or” operator, normal comma-separated lists serve as “or.” link  rel="stylesheet"  href="desktop.css"   media="screen  and  (min-­‐width:500px)" Styles are applied for screen devices that have a width of 500px or greater link  rel="stylesheet"  href="desktop.css"   media="screen  and  (min-­‐width:500px),  projection  and  (color)" Styles are applied for screen devices that have a width of 500px or greater, or color projection devices
  • 16.
    Media Query syntax Logicaloperator “not” negates the results of the media query and applies the styles if the conditions are NOT met. It negates the entire expression, not just media type. Use carefully. link  rel="stylesheet"  href="desktop.css"   media="not  screen  and  (min-­‐width:500px)" Styles are applied if the device is not a screen device with a width above 499px. This also means that styles WOULD be applied for screen devices with widths below 500px and other media types.
  • 17.
    Media Query syntax Logicaloperator “only” serves to hide style sheets from older or non-conforming user agents. Conforming user agents are instructed to ignore “only.” link  rel="stylesheet"  href="desktop.css"   media="only  screen  and  (min-­‐width:500px)" Would be ignored by non-conforming agents. Other user agents would apply the styles to screen devices with widths 500px and above.
  • 18.
    Media Query syntax MediaFeatures width color height color-­‐index device-­‐width monochrome device-­‐height resolution orientation scan aspect-­‐ratio grid device-­‐aspect-­‐ratio
  • 19.
    Media Query syntax MediaFeature values length width:500px keyword orientation:  landscape  |  portrait ratio aspect-­‐ratio:  16/9 integer color:8
  • 20.
    Media Query syntax MediaFeature prefixes In many cases, you can use the “min-” and “max-” prefixes to set less-than or greater-than ranges for your values width min-­‐width max-­‐width
  • 21.
    Media Query syntax Becareful! width  !=  device-­‐width (Honestly, even device-width != device width, or as PPK said, “a pixel is not a pixel*”) *http://www.quirksmode.org/blog/archives/2010/04/a_pixel_is_not.html
  • 22.
    Enough syntax! Let’s seeit in action! Visit mediaqueri.es for a gallery of sites using media queries
  • 23.
    Oh snap! Thatchanges everything! Except that it doesn’t. We still need to talk about how media queries work in the real world.
  • 24.
    “Media queries arefools gold...” - Jason Grigsby* So what’s his beef? Support for media queries isn’t that good *http://www.cloudfour.com/css-media-query-for-mobile-is-fools-gold/
  • 25.
    “Media queries arefools gold...” - Jason Grigsby* So what’s his beef? Having browsers scale images is a bad idea *http://www.cloudfour.com/css-media-query-for-mobile-is-fools-gold/
  • 26.
    “Media queries arefools gold...” - Jason Grigsby* So what’s his beef? Unnecessary resource downloading *http://www.cloudfour.com/css-media-query-for-mobile-is-fools-gold/
  • 27.
    “Media queries arefools gold...” - Jason Grigsby* So what’s his beef? Hiding elements doesn’t lower overhead *http://www.cloudfour.com/css-media-query-for-mobile-is-fools-gold/
  • 28.
    “Media queries arefools gold...” - Jason Grigsby* So what’s his beef? Media queries ignore the mobile context *http://www.cloudfour.com/css-media-query-for-mobile-is-fools-gold/
  • 29.
    Browser Support Browser Layout Engine MQ support Firefox Gecko 3.6+ Google  Chrome WebKit 10+ Safari WebKit 3.2+ Opera Presto 11+ Internet  Explorer Trident 9+ iOS  Safari WebKit 3.2 Opera  Mini Presto 5.0 Opera  Mobile Presto 10.0 Android  Browser   Android  WebKit   2.1 Nokia multiple s40 Blackberry  Browser Mango/WebKit 4.7.1 Samsung Android  WebKit ??? OpenWave ??? UC  Web proprietary NetFront NetFront Palm WebKit WebOS  1.4
  • 30.
    Another big problem...itdoesn’t just...work For mobile, media queries are typically used to check for screen size. They do not perform browser or device sniffing. The multitude of different screen sizes, resolutions, pixel densities, and default scaling preferences can cause serious problems with how media query-driven sites display.
  • 31.
    Oh...so....I guess wecan go now right? dang. Not so fast. Media queries CAN work, and can be an important part of your mobile development strategy... you just have to use them correctly, and combine them with other techniques
  • 32.
    Let’s talk strategy Mobile First* Popularized by Luke Wroblewski, it emphasizes starting the design process with mobile in mind. *http://www.lukew.com/presos/preso.asp?26
  • 33.
    Mobile first mediaqueries In terms of media queries, mobile first means starting with your mobile styles, and then enhancing designs for other screen sizes including desktop.
  • 34.
    Now, about mediaquery support... Respond.js from the Filament Group https://github.com/scottjehl/Respond (gzipped version is 1kb) css3-mediaqueries-js by Wouter van der Graaf http://code.google.com/p/css3-mediaqueries-js/ (15kb uncompressed) A mobile-first strategy makes using these libraries critical.
  • 35.
    Now, let’s tamethe viewport! CSS MEDIA QUERIES + VIEWPORT R Reflows content automatically, with no cramping or bloating. Works overnight, a soothing balm for your mobile ills Controls scaling and resolution with no bloating, dizzyness, or unpleasant aftertaste. A true joy for the home. = feel better by morning!
  • 36.
    Meta Viewport tags Metaviewport tags can be combined with media queries to help ensure consistent experiences. <meta  name="viewport"  content="width=device-­‐width,   initial-­‐scale=1.0"> what’s this all about then?
  • 37.
    So what canmeta viewport tags do? Meta Viewport properties width  =  [pixel  |  device-­‐width  ] height  =  [pixel  |  device-­‐height  ] You can set width and height to explicit pixel values, or set them to device width and height, which instruct the device to set the viewport width to the device screen width
  • 38.
    So what canmeta viewport tags do? Meta Viewport properties initial-­‐scale  =  0*  -­‐  10 minimum-­‐scale  =  0*  -­‐  10 maximum-­‐scale  =  0*  -­‐  10 These values allow you to control the initial scaling of the page (to control whether your page is initially zoomed out or not), and the minimum and maximum scaling allowed. * Android minimum is 0.01
  • 39.
    So what canmeta viewport tags do? Meta Viewport properties user-­‐scalable  =  [  yes  |  no  ] Controls whether or not the user can change the scale of the page. If the value is set to no, any previously set minimum and maximum scaling values are ignored.
  • 40.
    So what canmeta viewport tags do? Meta Viewport properties target-­‐densitydpi  =  [  dpi_value  |  device-­‐dpi   |  high-­‐dpi  |  medium-­‐dpi  |  low-­‐dpi  ]  ] Android Only: Allows you to target screen resolution. You can target a dpi value (70 - 400), the device dpi (prevents default scaling), or you can target one of three Android screen density categories. Content will then scale up or down if the resolution doesn’t match the target density. Essentially, it allows you to control how CSS pixels are scaled to device pixels. *For WebKit, you can use (-webkit-min-device-pixel-ratio: 2) to target higher density displays
  • 41.
    Let’s look atthat again... <meta  name="viewport"  content="width=device-­‐width,   initial-­‐scale=1.0"> This syntax tells the device to set the viewport width to the actual device width to ensure the proper media query styles are used, and set the initial page scale to 100%. Never use media queries without a meta viewport tag. Ever.
  • 42.
    What about resourceloading? OMG. I cannot believe I just ate all that!
  • 43.
    The truth aboutmedia query loading... <link  rel="stylesheet"  href="desktop.css"  media="screen,   projection"> <link  rel="stylesheet"  href="tablet.css"  media="all  and   (min-­‐width:  481px)  and  (max-­‐width:  768px)"> <link  rel="stylesheet"  href="mobile.css"  media="all  and   (min-­‐width:  0px)  and  (max-­‐width:  480px)"> This is very inefficient. All three CSS files will load, regardless of which media styles are loaded. This creates additional HTTP requests with no added savings. Combine these files using inline @media syntax.
  • 44.
    The truth aboutmedia query loading... #actionCall  {   display:  none; } This doesn’t help you either. If a widget or image is present in the element, it is still downloaded, regardless of the display property.
  • 45.
    The truth aboutmedia query loading... @media  //mobile  { #actionCall  {   background:  none;    } } @media  //desktop  { #actionCall  {   background:  url(big_ole_image.jpg);    } } This is better. If the mobile property is set to no background image, iOS does not download the desktop version. Sadly it seems that Android currently does.
  • 46.
    How can wecontrol resource loading? Modernizr 2 features both media query tests AND the YepNope.js library. This allows you to combine feature detection, media query success, and conditional resource loading. <BOOM> http://www.modernizr.com/
  • 47.
    How can wecontrol resource loading? Of course, if you prefer, you can roll your own. PPK reports in his own testing, document.documentElement.clientWidth and screen.width give the same results as the width and device- width media queries*. This means you could do this: if  (screen.width  >=  600)  {   //  load  resources } or if  (document.documentElement.clientWidth  >=   600)  {   //  load  resources } *http://www.quirksmode.org/blog/archives/2010/08/combining_media.html
  • 48.
    Media Query bestpractices Design with mobile in mind first Make the mobile styles your default styles and progress up Use fluid layouts to deal with minor screen size differences Combine CSS & JS files to reduce HTTP requests Minimize and gzip compress your code Use Data URL and CSS Sprites when you can Don’t use external libraries unless you really need to Consider using touch frameworks for interactivity
  • 49.
    Looks like goldto me! CSS MEDIA QUERIES R Reflows content automatically, with no cramping or bloating. Works overnight, a soothing balm for your mobile ills (That? Oh, that’s just the halo of truth...)
  • 50.
    So...where does thatleave us? Just like every other technique in your toolbox, media queries simply add to your capabilities. Are they right for every project? Of course not. Mobile design is far more than simply designing for a smaller screen. However, given the right circumstances, media queries allow you to optimize designs for the mobile environment in a way that we weren’t able to do before. Deciding when, and if, to use them is, after all, your job.
  • 51.
    THANK YOU james williamson| lynda.com jwilliamson@lynda.com @jameswillweb on the Twitter www.simpleprimate.com