Crafting a site with a Responsive Web Design and getting the images to be responsive too?

One of Verticas clients is launching a new eCommerce website soon. I was handed the task to implement a solution that would give the best experience for the site visitor. Not only should the site be using Responsive Design, also the site should be optimized for speed. 

The layout contained some very large PNG images with alpha transparency, the size of the images gave me a headache and it was clear that reducing the file size would gain a great performance boost.

Making the research for a way to detect the needed size of the image, and then only download an image in the desired size, I came along some interesting attempts. None of them was really what I wanted, or the setup with CDN and CMS made it impossible to use.

Most solutions, like the Picturefill and <picture> element or SRCSET both by RICG rely on defining fixed breakpoints, then downloading images in the fixed sizes according to these breakpoints.
To save time in both the layout and the implementation process, the site had to look fairly equal in all sizes, with just minor adjustments to spaces, font sizes etc. So using fixed breakpoints was not desired.

Then what did you do?

Sencha.io has a better solution with the src.sencha.io, but the price model and the beta tag kept me from using this. Instead foresight.js sounded like a way to go.
Basically the foresight script does a speed test and a resolution test (Device Pixel Ratio) then via my CSS rules download the image in the desired size.

The script does a speed test and stores the result for some (adjustable) minutes. The speed test is a great feature. Every day to and from work, I ride a bus in “EDGE Country” where my phone is unable to connect to the 3G network.
Every single page I request in the bus is slow and I often skip loading a slow page if it takes too long. The downside of the speed test is the need to make an extra download to test the connection speed. Hopefully the low resolution images used for slow network connections makes up with extra request being made during the speed test.

If the user rotates the device or re-sizes his browser, foresight checks if there is need for a new image to load. Only up-sizing will need a new download, as downsizing will just be done within the browser at the client.

Debugging

Getting foresight up and running was quite simple; getting everything to play nicely in all browsers needed some tweaks. Luckily the script includes an extra debug script that made debugging easy, because convincing your QA that everything works fine and that he just need to upgrade his tablet AND his internet connection is not always an easy task.

IE7 and IE8 had some problems, the script only downloads visible images in these browsers, and forcing preload is not an option. So sliding images in a carousel (sorry Brad Frost) would need a hint to foresight to check for new images in older browsers.

foresight.reload();

Example

I ended up with the following implementation, setting the data-src attribute and the noscript fallback image:

<img data-src="//yourcdn.com/images/2014102006_thumb.png" class="fs-img" alt="Remember your alt text" />
<noscript><img src="//yourcdn.com/images/2014102006_thumb.png" alt="Remember your alt text" /></noscript>

And the CSS adds the width of the parent element to the image:

.fs-img {
font-family: 'image-set( url({src}?width={requestWidth}) )';
display:inline-block;
width:100%;
}

Summing up

Pros

  • Only downloading the needed image sizes, not some predefined sizes
  • Noscript tag with fallback image to users with no script support
  • Re-sizing downloads larger images if needed
  • Network speed detection is very nice (spending 30 min every day in a bus with EDGE coverage keeps me remembering why this is important)

Cons

  • Debugging can be a little difficult, included script helps
  • The speed test requires an extra download
  • Defining string replace in CSS is limiting, JS would be more flexible
  • I would feel better if images did not need a script to execute
  • Extra markup is undesired
  • Hidden images is not downloaded, the ability to preload them anyway would be nice (thank you IE8)
  • Seems like there are only limited activity at the Git Repository
  • Adding features like half page width etc. would be useful
  • Responsive images with art direction use case, requires both markup and style and would be difficult to implement nicely

All in all, foresight might not be the perfect solution, but I found it to be a good approach for the moment being. I might even use it for the next project too.

And then a closing tip

As CSS attribute selectors are generally nicely supported, you can have different parameters for PNG and JPEG files, like adjusting the compression for the JPEG images for slow connections.

Also different servers, with different arguments can be supported, like CDN for product images and the Umbraco CMS delivers content images.

.fs-img[data-src^="http://yourcdn.com"],
.fs-img[data-src^="https://yourcdn.com"],
.fs-img[data-src^="//yourcdn.com"] {
font-family: 'image-set( url({src}?imageWidth={requestWidth}) )';
}

Or

.productRelated .fs-img {
font-family: 'image-set(
url({src}?w=250),
url({src}?w=500) 2x high-bandwidth)';
}

If it had not been for the transparent PNGs used all over the site, looking into the Retina Revolution concept could add more speed to the site.

2 Comments »

  1. Nice article… Very useful, how is hangtime before images start loading? Taking you load a large product catalogue the hangtime might be per image or?
    How about the resizing checks, is it based on checks on every single image? Guess it could be tough on the client!
    One last thing – could the script perhaps store the detected info in a cookie (for use via the CMS transformation of images.)? Could be very nice to only detect stuff in first request – and then just use the cookie from then on – maybe ignoring size changes (portrait vs landscape especially).

    Any comments on my ramblings?

  2. Hi Mads,
    First, the site is online now, so take a look at it https://www.xbytrollbeads.com/.
    At first page view, the script first makes a network connection test to see if it is feasible to download the high resolution images at all. So the images wont start download images until that test is done. After this, the estimated network connection speed is stored for some time and reused for sub pages.

    The size is calculated for each image, cause I can control the image sizes based on the size of the outer DOM element. That said, I find the script pretty fast doing the size calculation.

    What I like most about that script, is that I don’t predefine some fixed sizes, they are dynamic. Therefore the site is not only fit for the devices of today, but hopefully prepared for to serve better at the devices found under the Christmas tree for next xmas.
    Storing the sizes in a cookie will not help on orientation changes or browser resizes.

    Thanks for rambling and congrats with your new job.

Skriv et svar

Udfyld dine oplysninger nedenfor eller klik på et ikon for at logge ind:

WordPress.com Logo

Du kommenterer med din WordPress.com konto. Log Out / Skift )

Twitter picture

Du kommenterer med din Twitter konto. Log Out / Skift )

Facebook photo

Du kommenterer med din Facebook konto. Log Out / Skift )

Google+ photo

Du kommenterer med din Google+ konto. Log Out / Skift )

Connecting to %s