LQIP Battle Royale

 ⋅ 3 min read

Update #1 - Nov 21, 2017
The post has been updated with changes to primitive's usage notes.

LQIPs are an interesting technique to lower page load times, and are effectively used in websites like Google Images, Medium, Pinterest, Facebook & Quartz. In this post, I will discuss my experiences with some of the techniques, what worked best for me and how I implemented them on this website.

LQIP 101

Low Quality Image Placeholders are just that — pre-generated low-quality images (read: much smaller size) that can be displayed as placeholders while the page loads. We then use some Javascript to then lazily load the original full-quality image and replace the placeholder with it.

LQIPs were introduced in 2013, and have since been heavily adopted by many websites and in many interesting ways. "How to use SVG as a Placeholder, and Other Image Loading Techniques" by Spotify's José Pérez talks about the various techniques out there.

LQIP Shootout

If you're a blogger on Medium, you already have LQIP out of the box. However, if you're running anything else, you're probably gonna have to implement your own solution.

I primarily tested 2 libraries —

  1. primitive
  2. lqip

All benchmarks were run on a mid-2014 13" Macbook with a 2.6 GHz Intel Core i5 processor and 8 GB of DDR3 RAM.

Drag the slider (the little sign) on the left corner to swipe & compare images.

primitive
Original (254 KB)
primitive, 100 shapes (16 KB)
Original (254 KB)
primitive, 25 shapes (4 KB)

primitive took around 9 seconds to generate 25 shapes, and a whopping 26 seconds to generate 100 shapes.

A few things to keep in mind when using primitive are —

  1. primitive can give better results for geometric images than photos and photorealistic images, as it has to write fewer SVG paths.
  2. Currently, primitive has trouble generating SVGs when the source image has transparencies — see #54. This might not be a deal-breaker if you're not using transparent images, but I love making flowcharts which tend to have large transparent areas to keep PNG sizes small. I should've RTFM! I was using the command-line wrong, as pointed out by another user here.
lqip
Original (254 KB)
lqip (475 B)

lqip took only 0.4 seconds to generate the output! It is incredibly fast as all it does is generate a 14x14 px image. You might've noticed that the output is pretty close to Medium's implementation.

Javascript magic

Whatever LQIP implementation you choose to use, you'll need some JS on the frontend that will let you load LQIPs and swap them out with the original image when the user scrolls to the image's location.

lazysizes is a lightweight JS library that lets you lazy-load images, and demos a specific example for LQIPs. With the script injected in your page, you just have to —

  1. Add class="lazyload" to your <img> tag.
  2. Rename the src attribute to data-src.
  3. Include your LQIP URL or data URI to src.

Example

<img data-src="/path/to/your/image.jpg" class="lazyload" src="data:image/jpeg;base64,/9j/2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcUFhYaHSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUoKSj/2wBDAQcHBwoIChMKChMoGhYaKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCj/wAARCAALAA4DASIAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAABgQF/8QAJhAAAQMDAgUFAAAAAAAAAAAAAgEDBAAFERMhBhIiMTJBQoGhsf/EABUBAQEAAAAAAAAAAAAAAAAAAAIF/8QAGxEAAgEFAAAAAAAAAAAAAAAAAQIAAwURFSH/2gAMAwEAAhEDEQA/AK4VlslrnozKkxTEmnDJWz1CFRxtyjlfXPxRq7Xfg8XcCst3C+xlE/VSh1uecjN3RWDJtWmzEML4pt2rClSHdZev6qiLzVYlhDrlUjJ7P//Z"/>

Summary

While SVG is a compelling format for image placeholders, a few minor hurdles stop me from fully embracing them - primitive's issue with transparent PNG backgrounds, longer processing times and the overall jagged-ness (which, to me, looks more jarring than artsy/cool). For now, I'm sticking with lqip's super-small downsized images, as the output size is manyfold smaller while still being comparable to existing solutions like Medium's.