University of Missouri

Interface

Skip to search and archives

Responsive Images: 3 different coffee cup sizes

Responsive Images

Published on by Joshua Hughes | Posts by This Author

The advent of responsive design and HiDPI (or “Retina”) devices has created a real challenge for web developers: We need a way to provide multiple images to accommodate a variety of window sizes and resolutions. But also, we want a solution that doesn’t have extraneous image downloads, and is relatively easy for a content editor to setup.

This is our attempt to solve this issue.

How it Works

Say you’ve got a simple <img> tag:

<img src="photo.jpg" alt="A picturesque vista" />

Now, this image is the small version of the photo, one appropriate for mobile devices. However, if the user’s window is larger than 600 pixels, you want them to get a larger version. And if they have a HiDPI display, you want 2x versions to load instead.

So you create these additional files:

  1. photo-2x.jpg
  2. photo-large.jpg
  3. photo-large-2x.jpg

The question now is: how do you get these alternative versions to load under the right circumstances?

PHP: Find the Alternative Images

First, we use a PHP script to parse the entire HTML document, and for any <img> tags found, it will look for additional images on the filesystem by looking for certain filenames. We can configure it so that it automatically looks for images that ends with -large or -2x.

If the script finds any of these alternative images, it will encode that information by converting the <img> tag into something that starts looks like this:

<img data-src="photo.jpg"
     data-src-2x="photo-2x.jpg"
     data-src-large="photo-large.jpg"
     data-src-large-2x="photo-large-2x.jpg"
     alt="A picturesque vista"
     ...
/>

<noscript><img src="photo.jpg" alt="A picturesque vista" /></noscript>

The data-* attributes are a HTML5 feature that allow arbitrary bits of metadata to be inserted into markup. Note that the default src attribute is stripped so nothing gets downloaded in the meantime.

JavaScript: Conditionally Switch the src

Next, we use JavaScript to look for any image with a data-src attribute, and have it pick the correct src to use for the given window width and resolutions. Unless the window is resized and conditions change, only one image will be downloaded. If JavaScript is disabled, the user will receive the original photo.jpg through the <noscript> block that’s also added by the PHP script.

Example

If you’re viewing on a computer, try resizing the window.

Setup

First, download the files. Everything you need is in the dist folder. You’ll see a file structure like this:

  • dist/
    • css/
      • responsive-images.css
    • inc/
      • config-responsive-images.json
      • prep-img-tags.php
      • responsive-images-end.php
      • responsive-images-start.php
    • js/
      • responsive-images.js
    • html-template.php

Move these files into your site directory. The html-template.php contains the boilerplate for bringing it all together. Feel free to move the files to more logical locations for your project; just remember you’ll have to update the locations in the html-template.php file and everything in the inc folder should be kept together.

You can then customize html-template.php to include the rest of your template code and content.

Configuration

The script is highly customizable, and a number of options can be set in inc/config-responsive-images.json:

hidpi_image_class: This class (styled with width: 100%) that is set on the <img> tag whenever the src is set to the 2x (HiDPI or “Retina”) image. Defaults to hidpi.

hidden_image_class: This is a class (styled with display: none) set on the <img> tag before the JavaScript has set a src attribute. It’s removed when JavaScript is done processing the document. Defaults to hidden.

2x_pixel_threshold: Pixel density at which the 2x version of the image will be loaded. Defaults to 1.5.

2x_extension and filename_connector: The filename connector is used when looking for additional images to load. For instance, if you had a breakpoint called tablet and your filename_connector was set to @, it would look for a file called filename@tablet.jpg. It defaults to -.

Similarly, the 2x_extension is the suffix for HiDPI images. It defaults to 2x.

breakpoints: This script doesn’t come with any breakpoints pre-defined, but you can add as many as you want. This parameter takes an object that pairs a filename suffix with a media query.

Example:

"breakpoints":
{
    "large": "(min-width: 944px)",
    "medium": "(min-width: 656px)"
}

So if you had photo.jpg, it would change the src to photo-large.jpg if the window was at least 944 pixels wide, and if it was between 656 and 944 pixels photo-medium.jpg would be used. Otherwise, it would simply use the original photo.jpg.

SVG Support

SVG is increasingly a popular format for logos and other bitmap-style graphics. This script doesn’t test for SVG support by itself, but if it detects a .svg or .inlinesvg class on the <html> tag (the standard way Modernizr indicates SVG support) it’ll look for corresponding .svg files for every image.

Wrapup

The source for this script is available on GitHub. If you have any questions or comments please feel free to comment below, or email me at hughesjd@missouri.edu.

1 Comment

  • Serge Rodrigue

    Thank you so much Josh for this post.

    It’s the first time I heard about data-* feature in HTML5.

    We are just at the beginning of double DPI devices but it is good to know there is a responsive web design solution for these devices.

Comments are closed.