The BBC has a server-side image service which provides developers with multiple sized versions of any image they request. It works in a similar fashion to http://placehold.it/ but it also handles the image ratios returned (where as placehold.it doesn't).
The original BBC News process (and my re-working of the script) follows roughly these steps...
- Create new instance of ImageEnhancer
- Change any
div
s within the page (which have a class ofdelayed-image-load
) into a transparent GIF using a Base64 encoded string.- We set the
width
&height
HTML attributes of the image to the required size - We know what size the image needs to be because each
div
has customdata-attr
set server-side to the size of the image - We then set a class of
image-replace
onto each newly created transparent image
- We set the
- We use a 250ms
setTimeout
to unblock the UI thread and which calls a functionresizeImages
which enhances theimage-replace
images so their source is now set to a URL where the returned image matches the requested dimensions in the URL path (in my example below I userequestAnimationFrame
instead)- We also create an event listener for the resize event which fires a pubsub event of
imageEnhancer:resize
- We also create an event listener for the resize event which fires a pubsub event of
- We call
resizeImages
initially and then every time the pubsub event fires.- This function loops each
image-replace
image and changes thesrc
attribute to the new URL with the best possible match dimensions specified within the URL path (based on the dimensions required for the image). - If the resize event fires then we check the dimensions of the page and determine if we need a new URL to be used.
- This function loops each
The example code that follows is not production ready, you can't just drop it into your code base and expect it to work. It is a rough prototype I built in about 30 minutes to help demonstrate in a roundabout way how the BBC News responsive team were handling the enhancement of images. The code uses features only available to more modern browsers (e.g. I've tested it in Chrome 28 and nothing else so your mile may vary if you're using a different browser to look at the example).
I've also used the http://placehold.it/ service in place of the actual BBC News image provider. They don't work in quite the same way, but if you open the following HTML code in a modern browser (e.g. Chrome) and resize the browser window downwards you'll see the images change based on the current window dimensions. So rather than load a large image for smaller screens we swap out our images with images that are optimised for that screen size.
Notes about the rewritten example:
I should use livenodeList
otherwise we'll miss any images added to the DOM after ImageEnhancer is initialised.- I might be able to work-around the use of the base64 image
- Look at caching of image loads
We've went very similar approach with our project (LoveWall) but we've experienced rare issues with streamed images when replacing src directly to image. The problem was that if replace happens few times, after last image loaded it would throw http status code as (Failed) for some weird reason, and then would render image as corrupted.
In order to prevent that, each image has own Image js object, and if we need to load another image before this one loaded - we just remove it, that prevents http request to that image, and switches to new one. Then once it is loaded (onload) we just attach src to our actual element, and it appears immediately (as already in cache).