Jump to main navigation, main content

Archived entry | Matt Wilcox .net

Responsive <img> elements in HTML, for Responsive Designs

Update: I have developed this idea much further, and a production-ready version is available for anyone to use over at Responsive-Images.com.

A bit of background

Responsive designs are becoming popular at the moment. The idea being that one website displays (and potentially behaves) differently dependent only upon the size of the screen it is being displayed on. A quick look at some of the examples on MediaQueri.es will show you what this means. On the left is what you’d see on a device like an iPhone, followed by a tablet device like the iPad in portrait mode, next is a base-line desktop or iPad in landscape, followed by a full desktop resolution. Same site, but re-jigged on each through the “magic” of CSS Media Queries.

For many site’s this is a great solution, though it won’t be appropriate for all cases. There are legitimate reasons for pointing a mobile user to a completely different site on a mobile sub-domain. Which technique is the most appropriate depends on the content and use case. If you want to know more about that I’d recommend reading this round-up of the arguments for Responsive or Mobile techniques.

There are a couple of caveats with Responsive designs however, and they’re mostly technical. Cross browser support is mostly a solved problem (I highly recommend grabbing a copy of the excellent Responsive Web Design, and while you’re at it it wouldn’t hurt to get Adaptive Web Design which is tangentially related and also excellent). There’s one major issue which remains - serving appropriately sized <img/> elements to each design (usually for use with the Fluid Image technique).

The problem

Is fairly simple: small-screen sites only need small, low resolution <img/>’s. Large screen sites need large, high resolution <img/>’s. But the server has no way to know what resolution the client’s device is, so it can’t send the appropriately sized embeded images. You can for images supplied via CSS, because CSS has media queries. HTML currently has no such mechanism, and can’t know about the screen size to select an appropriate alternative source file.

An additional complication is the management of such images if you’re using a CMS. No one wants to hand-bake multiple resolutions of the same image. Likewise, there’s a heck of a lot of content that might already be in a CMS, so we could do with a solution that works dynamically on existing stuff rather than as an edit to the CMS itself. We want to retrofit responsive content images, not require a completely new CMS architecture.

There are some nice attempts at solutions, most tantalising to me is Filament Group’s experiment, which is a touch of brilliance. I think it can be improved a little bit though. It requires fiddling with HTML attributes on images you want to be responsive (which kills the idea of retrofitting to existing CMS content), and has a simple binary switch on whether an image is high resolution or low resolution. Considering that Media Queries are generally more granular than that, I’d rather take an approach where there’s an image sized specifically to each design/response. It seems to make more sense and strike a better balance between file size (bandwidth required) and image quality.

A solution

We can patch a solution while we wait for a HTML5 native method. To do that we need a touch of JavaScript, a couple of lines in a .htaccess file, and a small PHP script.

Here’s a run-through of the logic we want for this solution:

  • Use JS to set a cookie with the current screen resolution bracket (320, 480, 960, etc)
  • Catch all non-CSS image requests with a .htaccess rule and hand-over to a PHP script:
    • If there isn’t a cookie, just deliver the requested image as normal, else:
      • Use the cookie value as a path variable and check to see if an image of the same name exists at that path.
      • If the image exists deliver that image, else:
        • Check the default image folder to see if it exists there
        • If it doesn’t exist, fire back a 404, else:
          • Check the image dimensions
          • If the source image is less than the width of the cookie variable, deliver the source image itself, else:
            • Resize the source image to the width of the cookie variable
            • Save the new file in the appropriate path
            • Send the new file

This provides the ability to retrofit a responsive design to an existing website, whilst also providing built in caching so the images don’t need to be generated on every request.

View a demo

Comments

skip to comment form
  1. PiThailand posted 1 days, 4hrs, 31mins after the entry and said:

    Thanks for your all information. My friend had talk about HTML5 to me. But i haven't got opportunity to use.

  2. Aaron Gustafson posted 5 days, 12hrs, 7mins after the entry and said:

    I think this is a really good start, Matt. Despite how much of a PiTA it is to set up, I'd recommend switching to ImageMagick for image manipulation as it will allow for manipulation of any image type. My only other thoughts would be to move to fluid images (as you've mentioned), re-set the cookie on browser resize (as you've also mentioned), and to set some cache-related headers to get the browser to forgo re-requesting images that are already downloaded. I'd probably expire them on cookie expiration.

  3. Matt Wilcox posted 5 days, 13hrs, 8mins after the entry and said:

    Thanks Aaron. The cache-headers isn't something I'd thought of - I'll look into that as soon as I get chance. ImageMagick was on my radar but I've not had a look yet - I was wanting to stick with the common PHP libraries but it might be worth seeing if I can fork the script so it'll use IM if installed, but fall back to the GD lib stuff otherwise. I'm not entirely happy with the quality of the re-scaling GD is producing.

    Cool, the proof of concept seems to be ok, so I'll see how far I can refine it into something more production-ready smiley icon: smile Hopefully there will be updates on this soon.

  4. Kai posted 31 days, 8hrs, 0mins after the entry and said:

    What is the main purpose of the project? Reducing download time / improving speed? If so, did measure it if the request between htaccess, files, cookies and so on is faster than downloading a big picture? Im just curious in my attempt to find the best techniques for my first responsive designs smiley icon: smile

  5. Jordan Terry posted 162 days, 11hrs, 5mins after the entry and said:

    Thanks Matt. I have been trying to get my head around "responsive images" for quite a while now, I haven't understood why I couldn't just use CSS to resize the image, but having taken a look at this it all makes sense!

  6. Murray posted 268 days, 5hrs, 52mins after the entry and said:

    Looks to be an interesting technique.

    I'm seeing issues though with reverse proxy caching. The use of a cookie to serve a request throws a spanner in the works - a caching mechanism such as Varnish would need to use the cookie value as part of the caching key. This will add to complexity.

    Also, if you have rewritten your URLs for use with CDN, this technique will not work as the CDN can't do the cookie magic either.

    One alternate solution would be to rewrite the image URLs client side. Don't have the rules in Apache, have them in JS. This way Apache, Varnish, CDN etc will get a pure URL with no cookie, making it possible to handle.

From the archives

Other enteries filed under:

Web Development

Site information

Built with valid XHTML and CSS, designed with web standards and accessibility in mind. Best viewed in a modern browser [Firefox, Safari, Opera]

This domain and all content is a copy of my old website, for historical purposes only.