Responsive images – how to lazy load and multiserve images

I recently wrote about how we can prevent browser reflow when serving up flexible images by reserving space for the image so that the page will not reflow when the image is downloaded by the browser. This is done by using a padding-bottom trick that enables us to specify the height as factor of the width. This is a technique that works especially good for slow connections and slow CPU’s.

And this technique makes it much less expensive to insert images with JavaScript. Loading images with JavaScript has been a big no-no because of the reflow and delay it causes. But now that we have eliminated reflow, we can look at loading images this way again. And keep in mind, what we care about is the perceived speed for the user, not how many milliseconds (or seconds…) it actually takes to load it up. And since we now use JavaScript, another door openes up to us: we can choose which image to load based on the screen size and pixel density of the device.

So if we expand on the markup of the previous post, we have now added some image version information to data attributes on the noscript tag. The img inside the noscript tag is used if JavaScript is not enabled.

And working from this it is quite easy to use a script to load the correct image based on screen width of the device. We can also multiply the width with devicePixelRatio so that we get better quality on screens with high pixel density.

 

The result

  • No reflow
  • Images only load once
  • No .htaccess, PHP or backend hack
  • Small size to small screens
  • Not dependant on cookies
  • Cachable
  • Sensible fallback if JavaScript is turned off

Example on how page size varies: (Taken from the demo site):

  • When getting 240px images: 500kb
  • When getting 320px images: 644kb
  • When getting 480px images: 902kb
  • When getting 640px images: 1.13mb

Demo and code

See the solution in action: http://andmag.se/responsive-images/

The code is available on github: https://github.com/4nd3rs/responsive-images

I would really appreciate (both positive and critical) comments or improvement suggestions to this solution!

UPDATE

Added alt attribute to the image tag for validation and accessibility.

Published by

Anders M. Andersen

Digital Project Manager and Front End Developer.

  • I really like this approach but I have heard that google will not read the content in noscript tag?.. if so then this would not be a good way to do it if you care about SEO.. :(

    Any ideas on that?

  • I really like this approach but I have heard that google will not read the content in noscript tag?.. if so then this would not be a good way to do it if you care about SEO.. :(

    Any ideas on that?

  • Paolo

    I start by saying that I’m a novice, but wouldn’t be possible to do a similar thing in php (like for a multilingual website that loads the texts in the right language depending on the browser language), just using javascript to detect at the beginning the screen size? in this way the SEO wouldn’t be affected, am I wrong?

  • Paolo

    I start by saying that I’m a novice, but wouldn’t be possible to do a similar thing in php (like for a multilingual website that loads the texts in the right language depending on the browser language), just using javascript to detect at the beginning the screen size? in this way the SEO wouldn’t be affected, am I wrong?

  • I’m no expert on SEO either, but I’m pretty sure that Google (and most other bots) parses Javascript, so this should not be a problem.

  • Yossi

    Useful. Thanks!

  • Yossi

    Useful. Thanks!

  • jason

    What SEO would matter from an image tag? I’m wondering…

    The ALT tag could be covered by static “image caption” text below the image, which would be read by google.

  • If you want google images and other image services to index your images this would matter. But as I said, I think all of them are also processing JavaScript so this should be safe. And if they are not processing JavaScript they should read the noscript tag, so I cannot see a problem here :-)

  • jason

    Sweet, thanks! This is looking to be a very promising solution :)

  • Pingback: Responsive images – how to prevent reflow : Anders M. Andersen()

  • Rasmus Fløe

    Wow, this is incredibly close to what we’ve been doing at work. Almost down to structure, class and attribute names :)

    The main differences being:

    1. Images are only loaded as they scroll into view.
    2. The image container is expanded via an after pseudo element (which then has width: 100%, padding-bottom xx%)

    No. 2 is important for no. 1 to be viable (avoid reflow as soon as css has loaded).

    It’s live at: http://www.dr.dk/nyheder

    Previously we used (and are still using in parts) blank placeholder gifs for each ratio. But the no. 2 technique eliminates the (granted very few) extra requests and potential reflow before placeholders got loaded.

  • Hi Rasmus!

    Interesting that you use this technique already!

    Do you remove padding bottom with the Javascript when you insert the image? That is interesting because then you do not need to have position:absolute on the image.

  • Hi Rasmus!

    Interesting that you use this technique already!

    Do you remove padding bottom with the Javascript when you insert the image? That is interesting because then you do not need to have position:absolute on the image.

  • Rasmus Fløe

    Yes :) – no position:absolute is used. The :after pseudo element (that is expanding the image container before image load) gets its padding-bottom through the ratio-x-x class on the image container. When loaded the actual image is inserted into the container and the ratio-x-x class removed (thus also the :after element). Only the area covered by the image is repainted/composited – and in ideal conditions it happens already before users have scrolled the images into view (except for images already in the viewport of course).

    With only lazyloading the images that are visible in the viewport from start pageload is reduced drastically for most of our pages (fairly image heavy).

    It works really well.

  • Yes, Google parses (and in some cases execute) javascript for indexing, plus you’ve got a sensible no-script img tag, So there should’t be an problem with Google picking up the images.

  • Yes, Google parses (and in some cases execute) javascript for indexing, plus you’ve got a sensible no-script img tag, So there should’t be an problem with Google picking up the images.

  • I like this solution, it seems to render really quick and without reflow in the little bit of testing I’ve just done – do you have any sites, other than your demo, where the technique has been implemented “for real”?

    I’m also wondering a bit about accessibility issues – someone elsewhere has mentioned the lack of an alt attribute in relation to SEO, but an alt tag is important from an accessibility viewpoint and is also a required attribute of an img element. It would be great if this concept could be tweaked to include alt.

  • Hi James, Thanks for the feedback!

    The project that I work on right now use this technique. The site is not live yet, but we have not had a single issue with this technique since we started using it. It is a large site (in terms of pageviews, and the only thing we have considered is to not serve images that are too large. Maybe just have a few highres images and then have the others in lower resolutions to save bandwidth.

    This site uses a similar technique: http://www.dr.dk/nyheder/

    Adding the alt tag should be very easy, I’ll see if I get around and do it some day… ;-)

    2013/1/21 Disqus

  • daniel

    Mhh,

    I’ve got no clue how the setup process looks like..
    Soooo many files on github..
    No manual …

  • daniel

    Mhh,

    I’ve got no clue how the setup process looks like..
    Soooo many files on github..
    No manual …

  • Pingback: Web page performance: How to optimize image loading? | Julien Renaux Blog()

  • In your load-on-scroll technique, what happens when someone loads a page on a laptop or Wi-Fi-only tablet, goes offline, and begins to read the page? Some people like to read pages while riding the bus to and from work and aren’t willing to pay hundreds of dollars a year to have cellular Internet.

  • Rasmus Fløe

    Requests for images while offline will just fail (timeout) and be represented with grey boxes (ensuring layout stays the same – no jumping text). The page would still be fully readable – and no bandwidth is wasted.

    The case for using load-on-scroll is of course not pages with a couple of images – but pages with upwards of a 100 images (which was our case). And – yes that is too many images/too much content for a single page. But that’s another battle ;)

  • You claim “The page would still be fully readable” but I don’t see how that’s the case if the text of the article relies on information presented in a figure, such as an infographic or a still from a film being discussed. Have you made sure that the text in every alt= attribute is a complete substitute for the corresponding image? Is alt= even allowed to contain the thousand words that conventional wisdom holds a picture to be worth?

    You also mention “too much content for a single page.” The opposite creates another pet peeve: every time I read three paragraphs, I have to wait for an Internet connection and then endure another page load, another hit to 20 different ad and tracking servers, and another execution of 20 different onload scripts. Is there a means to load all pages of an article before heading out? Should there be one?

  • Rasmus Fløe

    “Readable” means text content – images are secondary content by nature (linked to from html via src=).

    Your infographics are screen reader friendly SVGs inlined as part of your actual content – maybe even with a figure caption – so they sidestep the loading techniques described here. Photographs/stills/etc are covered with alt attributes.
    As you are already thinking of people using screen readers no one should be missing out by not being able to see an image.

  • Couple of months ago I published an article and a library that is 100% SEO-friendly. I think you can use the technique to improve your code. It uses the basic . Take a look at http://ivopetkov.com/b/lazy-load-responsive-images/