Automating Responsive image generation

Wednesday 16 July 2014

Photo by PhotKing / CC BY

I’ve spent a lot of time working with Grunt in recent months searching for the perfect workflow

One of the key rules when building a Responsive website is to try to reuse as much of the HTML, CSS and JavaScript as possible, applying breakpoints and additional styles only as the layout breaks and the content requires it. This ensures we don’t have to maintain different code bases for different device widths, and keeps the lightest page weight – the overall file size of the page – possible on each device.

Heavy page weight is a big issue for mobile devices particularly, where the network connection may not be as fast as that for desktop devices. By minifying and uglifying our code, and ensuring our text-based site assets – HTML, CSS, JavaScript, etc – are served using gzip compression, we reduce the amount of data downloaded across the network, reducing the time taken to load. There are many articles written covering the many ways to reduce the size of HTML, CSS and JavaScript files by using different character-removal techniques, but the reality is they are only saving a small number of bytes compared to the overall size of the page. There’s little point spending hours optimising relatively small HTML, CSS and JavaScript file contents if you then include a 500KB image on your homepage which takes several seconds to load.

Image optimisation software such as ImageOptim for Mac and build tool tasks such as grunt-contrib-image-min for Grunt and gulp-imagemin for Gulp allow a reduction in image file size. However, these do not solve the problem of displaying large-size images on small-screen devices. Loading more pixels than the screen can display means wasted data from these large files, and places additional pressure on the device’s GPU to resize the image appropriately. It’s important to have a process in place to reduce image sizes for display on small-screen mobile devices.

There are a few techniques for displaying Responsive images on your website, allowing different images to be specified for different screen sizes and resolutions as appropriate for the device the site is being viewed on.

When producing in-page content images, use the new HTML <picture> element. For less important images, those not relevant to the page content, or those used for aesthetic purposes only, set these as background images via CSS and use the ‘background-size’ style property to display them appropriately based on the site layout.

I’ve spent a lot of time working with the JavaScript task runner Grunt in recent months searching for the perfect workflow, and I wanted to integrate image resizing into my build process to get the benefits of automation. So I came up with a Grunt task called "Grunt Responsive Images". This task takes your original, large source image and, based on the parameters specified, creates images at different sizes and resolutions which can then be used for display on a web page using one of the Responsive image techniques mentioned previously. You can even specify multiple size options for each image, and the task will output them together with a given suffix (e.g. cat-small.jpg, cat-large.jpg).

Let’s take a look at some of the options available in the task.

Setting the size option to the following array value produces three images for each image in our file directory, with the suffixes -small, -medium and -large appended to their file names.

    name: "small",
    width: 320
    name: "medium",
    width: 640
    name: "large",
    width: 1024

Images can be resized by width and/or height. Specifying one or other will keep the aspect ratio the same as the original image, but if both are specified then the image will be resized and cropped. If a name is not specified, then the file will be suffixed with the width and/or height – e.g. my-image-320x240.jpg.

There are a number of other options available – such as changing the quality of the resulting image, adding a suffix for retina-optimised images, and for changing the filename separator.

Full instructions on how to install and use the plugin are available on the task’s Github page.

Once the Responsive images are generated using the task, they then need to be included on a web page.

For the new HTML <picture> element, we specify multiple source files – one for each image, together with a media query to match. A standard HTML <img> tag will be the fallback for browsers that cannot load any of the source images, including those that don't support the <picture> tag. For example:

    <source srcset="assets/img/wedding-large.jpg" media="(min-width: 1024px)" />
    <source srcset="assets/img/wedding-medium.jpg" media="(min-width: 640px)" />
    <source srcset="assets/img/wedding-small.jpg" />
    <img src="assets/img/wedding-small.jpg" srcset="assets/img/wedding-small.jpg" alt="Andi's Wedding Day" />

At the time of writing, browser support for the <picture> element is very limited, with a working implementation due in Chrome version 38 and Firefox version 33, with Safari support due in the coming months. For browsers that do not support <picture>, we can include the picturefill polyfill. To support the picturefill polyfill in Internet Explorer version 9, we will need to add an additional IE conditional comment, as follows:

    <!--[if IE 9]><video style="display: none;"><![endif]-->
    <source srcset="assets/img/wedding-large.jpg" media="(min-width: 1024px)" />
    <source srcset="assets/img/wedding-medium.jpg" media="(min-width: 640px)" />
    <source srcset="assets/img/wedding-small.jpg" />
    <!--[if IE 9]></video><![endif]-->
    <img src="assets/img/wedding-small.jpg" srcset="assets/img/wedding-small.jpg" alt="Andi's Wedding Day" />

The Grunt Responsive Images Task is a quick and useful way to automatically generate Responsive images for your website without relying on any server-side implementation. Have a look at the GitHub repo to gain a deeper understanding, and if decide to use it on your own site, please do drop me a tweet @andismith to let me know!

About The Author

In his role as Technical Architect at AKQA, Andi is obsessed with creating great web experiences and helping make the web a better place for both users and developers. He also runs to teach others about in-built browser tools.