In a past post I dissected a technique used by Medium to display images, transitioning from a blurry image to the final one. Since then I have found some more sites following a similar approach. Let’s see how Quora, Quartz and Clicktorelease do it.
Images are the largest assets on web pages and they account for two thirds of the bytes. Image optimisation and choosing the right image format is paramount. In addition, some sites are also using small thumbnails as placeholders while the final image hasn’t loaded yet. This technique is also called “blur-up“. It basically tries to improve user’s perceived performance while also saving data traffic when combined with lazy-loading.
There are other alternatives to this approach. One of them consists of using a single JPEG image, tweaking its scan script to quickly render an initial pixelated version of the image and progressively load the final image in several scans. I recommend you having a look at Progressive JPEGs and green Martians to know more about this.
Also, if you like images optimisation, follow Cloudinary’s Blog, full with useful posts on this topic.
Take a look at the following video, recorded when accessing a page on QZ.com with a throttled connection:
Quartz’s implementation follows this steps:
- Request a small
<img/>that will be blurred. In their case, they use 50px width images, with a 80% quality.
- Apply blur effect using a CSS filter.
- Request the large image.
One of the interesting points about Quartz is that their markup specifies the large image using the syntax for responsive images. The main difference is that they use a
data-srcset attribute, so they control when to make the request and prevent the browser from requesting the large version of the image when the markup is parsed.
I find this approach very neat since they try to follow the “standard” way to serve images, adding extra bits to lazy load and animate the transition.
Quora also implements a blur-up technique for the images in their posts. To see an example head to this page.
Here we see what the page looks like when displaying the blurry placeholder:
Let’s dive into the code to see what’s going on. First of all, let’s focus on the HTML markup:
Why to use both
master_src image is the one requested when clicking on the image to get a larger view.
In Quora there is no blur effect applied. They use
canvas.drawImage() to render the tiny thumbnail in the canvas. You can see this by inspecting their code, that lives in the
shared/lazy_load_images module that gets bundled in the main JS file:
In short, Quora’s technique consists of:
- Draw an inlined tiny PNG in a canvas
- Request the large image using WebP (if supported) or other format.
- Set the large image as source for the
<img/>element, animate its opacity and hide the canvas.
The most interesting bit here is that the thumbnail is not the image itself, but the values of the DCT matrix for the thumbnail, which makes the payload really small.
These are the steps to load an image:
- Make a request for the
thumb-srcimage. It is a 16x4 PNG thumbnail whose size is usually in the 300B.
- Create a
<canvas/>and draw the image resulting from the calculation the inverse DCT of the thumbnail.
- Request the large image using the
original-srcurl. If the browser supports the webp image format, then “.webp” is appended to the src and a webp image is requested.
The initial markup looks like this:
I think it is a very good example of progressive enhancement, providing a
<noscript> alternative, and going all the way up from a solid background-color, to a blurry gradient and finally the large image with support for webp.
If you want to follow a basic example, check my “Reproducing Medium loading image effect” pen. Let me know if you come across any other site implementing these techniques.