How to build truly responsive images

UPDATE: it looks like Scott Jehl has already beaten me to the punch, so check out his github project!

So, I was almost asleep, and this idea popped into my head. I want to write it down for two reasons:

  1. So I don’t forget it.
  2. To see if anyone else agrees, disagrees, or sees any flaws in the idea.
Basically, I think I have figured out how to make images ridiculously responsive
  1. in a syntax that is logical and 
  2. in a way that can be powered by javascript and 
  3. fails gracefully to non-javascript supporting clients
The code starts out as simple as:
<image data-alt="Some image" data-width="300px" data-height="300px"
  id="my_image" class="some_class">
 
  <source src="/images/high-dpi/image.jpg"
    media="screen and (-webkit-device-pixel-ratio: 2.0)" />
  <source src="/images/print-dpi/image.jpg" media="print" />
  <source src="/images/regular-dpi/image.jpg" />
  <img src="/images/regular-dpi/image.jpg" width="300"
    height="300" alt="Some image" />
</image>

With no javascript, nothing but the <img> tag is displayed, and everything is happy.

With javascript, we run a system which turns it into the following (this becomes easier if we can evaluate media queries in JS, but I’m not sure if we can do that, so I’m showing an alternate way):

<style>
  #my_image {
    background-image: url('/images/regular-dpi/image.jpg');
    background-repeat: no-repeat;
    background-size: 300px 300px;
  }
  @media print {
    #my_image { 
      background-image: url('/images/print-dpi/image.jpg');
    }
  }
  @media screen and (-webkit-device-pixel-ratio: 2.0) {
    #my_image {
      background-image: url('/images/high-dpi/image.jpg');
    }
  }
</style>
<image data-alt="Some image" data-width="300px" data-height="300px"
  id="my_image" style="width: 300px; height: 300px;">
</image>

And now for the fun part – we can use document.getElementById(‘my_image’).style.backgroundImage to get the right image!

This means that the last and final step then turns into:

<image data-alt="Some image" data-width="300px" data-height="300px" id="my_image">
  <img style="width: 300px; height: 300px;" src="/images/high-dpi/image.jpg"
    alt="Some image" width="300" height="300" />
</image>

Which should make it happy with screen readers and other similar systems.

This approach has a few distinct advantages:

  1. It leverages existing tools for defining when to load a particular image (media queries)
  2. It provides a graceful fallback for no javascript support
  3. It (hopefully) will be relatively close to whatever is selected for moving forward in a browser integrated solution, as it fits with the patterns already established.

So that’s it. That’s my master plan. What do you think?

2 Comments

  1. cordoval

    to understand something we need a background, what was the non efficient solution so this can be a contrast of. If you provide this then everything will make sense. I haven’t yet grasped the idea really.

    Reply

    • Jacob Mather

      The background is basically that there is no good, standard, way to handle providing higher (or lower) resolution image assets to users with different pixel densities.

      The canonical example right now is the iPad 3 which has double the pixel density of most other devices out there, with a huge screen as well. The problem is that this huge screen makes it absolutely obvious that the images are lower resolution than the device is capable of displaying.

      There are a few solutions out there geared specifically towards providing double resolution images, but I’ve not heard of any solution from anyone for providing double resolution, .75 resolution, and 1.5 resolution images with a common syntax.

      When I started to think about the solution, I cam to this one, which makes sense, and also opens some other fun doors.

      When you enable media queries to power which source is selected, you also give a powerful way to not only provide different images for different screen densities, but you can provide different images for different widths! You could provide a 900×100 image for your ‘desktop view’, and a 500×300 for your ‘mobile view’, with the same code, and have it easily maintainable and understandable.

      The system would only run at the initial startup because you really only care about the particular device being used. Most people don’t resize their browser, so 99% of people will never notice that it doesn’t adapt to browser size changes.

      Now this still doesn’t solve the issue of the double image download hit (i.e. you’d download both the fallback image and the actual one used), but as long as you pass your lowest resolution mobile image as the fallback image, the hit should be minimal, especially if you make appropriate use of cache settings on your web server.

      Ultimately the double-download penalty will only be truly resolved by standards bodies coming up with a canonical solution to do this, but this seems like the best way to patch things in the mean time.

      Reply

Leave a Reply to cordoval Cancel

*

twitter