PictureFill – A responsive images technique

Responsive Images

If your web application takes more than 3 seconds to load, you will soon get a call from the the latency police to explain yourself. Users expect snappy applications otherwise they will move on to the next website with better user experience. For businesses, you can not overstate the importance of fast applications as this could be the difference between success and failure. One of the reasons most web pages take a long time to load is the amount of requests made by the browser and the size of the files that need to be pre-loaded. Reducing the amount of requests, is at the core of improving user experience.

Recently in my day job, I was assigned a task of creating a prototype to demonstrate responsive images. Fishing rod in hand I headed off fishing for some new techniques. There is no shortage of server and client side techniques but I settled for PictureFill.

What is PictureFill?

PictureFill is a responsive image technique devised by Scott Jehl that makes use of the proposed picture element and media queries to serve images based on browser window size.

How does it work?

An img element is created on the fly using JavaScript based on the source and media query specified within the picture element. This prevents unnecessary overheads that are otherwise incurred by pre-loading large files, especially on small or low speed devices.

Implementation – Some code please!

Head off to the Github code repository and download the code files. The code is very well documented and includes examples. I will nonetheless give a quick run down on the html markup.

PictureFill HTML markup

<picture data-picture data-alt="big pebbles">
  <source data-src="img/pebbles_small.jpg">
  <source data-src="img/pebbles_medium.jpg" data-media="(min-width: 400px)">
  <source data-src="img/pebbles_large.jpg" data-media="(min-width: 800px)">
  <source data-src="img/pebbles_extralarge.jpg" data-media="(min-width: 1000px)">

  <!-- Fallback if no JS -->
    <noscript>
      <img src="img/small.jpg" alt="big pebbles">
    </noscript>
</picture>

In the snippet above, I use the picture element to nest all the various image sources using, well the source element. Note that I also specify the screen resolutions using media queries passed as values for the data-media attribute. The beauty here is the ability to cater for as many screen resolutions as you want.

For users with JavaScript disabled, we have a fallback image which is wrapped in noscript tags. This piece of code will not be executed by browsers running JavaScript.

Well as usually, IE demands special treatment. Using IE conditional comments we can provide a one-size-for-all image for IE8 and below as Media Queries are not supported here. For example if I wanted to serve the medium image to IE8 and below, I can nest the following inside the picture element:
<!–[if (lt IE 9) & (!IEMobile)]>
  <source data-src=”img/thumbs/pebbles_medium_thumb.jpg”></div>
<![endif]–>

If you are understandably apprehensive about using the picture element as it’s still in draft status with the w3c, you can replace the picture and source tags with the div element. Remember however to make the switch in the JavaScript as well i.e replace all the picture instances with div. My take on standards is that; they do not really mean that much if the browsers do not implement the module in question. After all users are not concerned about whether the your code is legal or not. That’s not to say that we should totally disregard semantics and standards. Word is that a few browsers have began implementing the picture/source model.

Summary

To many this might seem a very involved workaround to a problem that does not yet have a standardized solution, but until a fix comes along, this is a semantic workaround for the purist. As I mentioned earlier, there is no shortage of polyfills and workarounds in the web dev community, but this by far gets my vote.

Useful resources

  • Adaptive Images – a server side responsive images technique
  • HiSRC – a jQuery plugin for responsive images
  • Senchia.IO – cloud based service for mobile development.

Media Queries and responsive web design

Media Queries

Try viewing my site on a small device or resize your browser window, and you will notice that the page content ‘responds’ to the size of the viewport by readjusting the layout. How did you do that? you might ask. Well, I will tell you and no, I won’t have to kill you. Say hello to a fairly new paradigm that is responsive web design courtesy of Media Queries.

What are Media Queries?

As can be deduced from the name, Media Queries are a means of targeting media types by way of their characteristic features. So for example; you can define a media type e.g screen or projection and then specify a width, height, orientation or color. This gives us as developers a lot of leverage and enables us to easily and quickly optimise our web applications with minimal extra development and without resorting to ‘browser sniffing’.

Let me demonstrate.

Media queries demo

@media screen and (max-width:600px){
  #med-q-demo {
    background:#FE57A1;
  }
}
This box will turn hot pink if browser window is less than 600px

In the very trivial example above, when the browser viewport is less than 600px (including the scroll bar), the media query fires the encapsulated CSS. It doesn’t take a lot of imagination to see the power put to our disposal. Go on, you know you want to see that hot pink background; resize your browser or view this page on a small screen device.

Syntax and declaration

Media queries are declared the same way CSS is applied but can be used with JavaScript as well.

Method 1

Add a link element in the head section of your document to call an external stylesheet:
<link rel=”stylesheet” media=”only screen and (max-width:480px)” href=”small_screens.css” />
A BEST PRACTICE: Create a basic stylesheet for your mobile users first, then one for tablets and desktop users. Taking this approach means, you avoid loading large assets which affect load speeds and are bandwidth intensive on mobile devices. Then use Media Queries to load the appropriate stylesheet. I can hear you saying; but there is no support for Media Queries in IE8 and below! We can get around this by using conditional comments. This is a mobile first approach which is advocated by a growing number of web developers.

Method 2

Call an external stylesheet inside another stylesheet using the @import directive:
@import url(‘small_screens.css’) only screen and (max-width:480px)
This is however considered an anti-pattern as the rest of your CSS will stop loading while the @import file loads, which might result in the user momentarily viewing the un-styled version of your page.

Method 3

Embed the Media Queries in your stylesheet using the @media rule:
@media only screen and (max-width:480px){ /*– your CSS rules –*/ }
In cases where the application does not warrant a separate Media Queries stylesheet, you can add your query within your normal stylesheet.

Method 4

We can also use JavaScript to work with Media Queries by tapping into window.matchMedia which returns a mediaQueryList object. This object has two properties:
matches: returns a boolean on a query.
media: serialised media query list.
Here is the syntax:
var smartPhones = window.mediaMatch(‘(max-width:480px)’).matches
The simple code above will return true if the viewport size is 480px or less.

NOTE: we use the only value to hide the rule from old browsers that do not support the syntax. This is ignored by browsers that support Media Queries. We can also use not to negate the Media Query.

Media features

Media features constitute any information about the host medium e.g width, height, orientation, pixel-ratio, and pixel-ratio. Most features require a value in the expression part of the Media Query which takes the following syntactical form:
@media media and (feature:value) { CSS rules } Note that this does not always have to be the case. For instance you could just test for the presence of the feature; @media media and (feature){ CSS rules }

Width and Height

width and height refer to the width and height respectively of the rendering viewport including scroll bars on desktops. These two features can be prefixed with min- and max- as the non-prefixed variants will in most cases be too specific. A practical example would be if you wanted to add a background image for browser windows over a certain width, you would do something like this:

min-width in action

@media screen and (min-width:500px){
  body { background-image: url(bg_img.png) repeat-x;  }
}

The Media Query in the above snippet tests for browser windows that are atleast 500px to apply the background image. In real world applications it’s recommended to limit the number images loaded on smartphones and tablets as they affect page load speeds and users’ bandwidth. The above technique lends itself to this. You could also use other techniques such as responsive images.

Device-width and height

This works exactly the same as the preceding example except the width is a reference to the device on which content is rendered as opposed to the browser window. As with the width feature above, device-width can be prefixed with min- and max-. This is especially useful for targeting smartphones and tablets. Let me demonstrate:

device-width

#wrapper { width:600px; }
 #wrapper div { float:left; width:290px; margin:0 10px 0 0; }
 @media screen and (max-device-width:320px){
  #wrapper { width:auto; } 
  #wrapper div { float:none; width:auto; margin:0; }
 }

In the code above, we have a wrapper div with a fixed width that contains two divs with explicit widths. This is fine for desktops but is not ideal on small devices e.g iPhones because screen real estate comes at a premium. To solve this, we use a Media Query that tests for devices with a maximum width of 320px (iPhones fall in this category), and we apply rules to remove the floats and explicit width which forces our divs to stack. View demo.

I am not going to go into details about all the Media Features but here is a list of some and what they do:

  • Orientation : used to optimise pages based on whether the device is in a horizontal orientation (width greater than height) or vertical orientation (height greater than width). @media media and (orientation:value) { CSS rules } This Media Feature is best suited for controlling content display on handheld devices.
  • Aspect ratio : Tests width-to-height ratio@media media and (aspect-ratio:ratio) { CSS rules }

Multiples

You can test for more than one Media feature on a media type. Take an example where you wanted to test for tablets in a horizontal orientation. This is the syntax:
@media only screen and (min-device-width:768px) and (max-device-width:1024px) and (orientation:horizontal) { CSS rules }

In a nutshell

Building responsive web applications is undoubtedly the future of web development. More people than ever before are viewing content on the go thanks to ever faster network speeds on tablets and smartphones. It is on this premise that as web developers we must move away from the mindset of building applications that only target a given resolution.

The Media Queries module has Candidate Recommendation status and therefore considered ready for implementation.