Hello, fellow web perf enthusiast! Contribute to the 2024 edition happening this December. Click.

Web Performance Calendar

The speed geek's favorite time of year
2017 Edition
ABOUT THE AUTHOR

Tobias Baldauf (@tbaldauf) leads the Core Frontend team at trivago. He creates DevOps tools, image optimization algorithms & speaks at conferences. He's a proud dad, mindful veggy & music lover. Find out more at who.tobias.is

tl;dr:Image placeholders in SVG are ready for prime time thanks to browser support and good rendering performance. By automating SVG shape creation that mimics main features visible inside an image and compressing the result appropriately, we can achieve SVG-based image placeholders weighing in at only ~400 bytes. SQIP is a tool to make this process easy to integrate into your deployments.

Raison d’être

Different Image Placeholder Techniques Overview Image placeholders exist in a variety of fashions: grey boxes in skeleton screens, placeholder boxes that show the predominant color of the image that will later occupy the space, boxes showing color gradients made from two dominant colors taken from the image, images showing outlines or major shapes to hint at upcoming image contents and actual low quality raster images downscaled to a few pixels, saved in low quality and blurred to provide a preview of image contents.

These techniques are used in two major areas: 1) while rendering a page layout, reserving the space that will be occupied by raster images and avoiding reflows as well as 2) as a part of image lazy-loading techniques in which placeholders will show until users interact with the page and high-resolution raster images load asynchronously. Check out Dean Hume’s article in this year’s Performance Advent Calendar on progressive image loading with SQIP for a hands-on implementation of this technique that uses Intersection Observer for reliable lazy loading.

Many major websites have adopted these image placeholder techniques: After Guy Podjarny incepted LQIP in 2012, Akamai and Cloudinary adopted it as part of their image optimization tools, Google started using colored placeholders, Facebook, Pinterest and Medium made significant impact with their LQIP implementations and the most popular JS libraries for responsive images include LQIP implementations.

The Importance Of Being Byte Sized

LQIP vs. SQIP On the low end of the byte size spectrum of image placeholder implementations, we have skeleton screens and colored boxes, weighing only a few extra bytes each, but providing no preview of image contents.

On the high end of the byte size spectrum, the LQIP technique ships an actual raster image, which gives a good initial impression of visual contents to come, but weighs in more heavily in byte size.

If we disregard Facebooks’s native app implementation of shipping a custom image decoder letting them hardcode image headers and other data, which enables them to ship LQIP images with only ~200 bytes, the current minimum byte size for LQIP raster images in browsers is ~400-600 bytes.

At this byte size, LQIP raster images often look distorted and coarse due to compression artefacts, especially on HiDPI screens. Many common LQIP implementations therefore aim for preview images of ~2kb in size, which provide a better initial visual impression but come at the cost of significantly increased byte size.

Attack Vectors

Different Image Placeholder Techniques Overview Recently, vector graphics implementations have emerged to provide new alternatives to existing LQIP techniques: by tracing outlines or showing shapes of visible objects from an upcoming image, users may get an idea of its contents. While these approaches deliver comparatively small SVG files and outlines and shapes have an artistic value, they lack color information and a level of detail that raster LQIP images provide.

Back in November 2015, I first pursued the idea of using SVGs to solve the problem of producing visually pleasing image previews that have small byte size. I named it "SQIP", pronounced \skwɪb\ like the non-magical folk of magical descent in the Harry Potter universe, because of it being an LQIP implementation in SVG and also because it is a no-magic tool based on truly magical software written by others.

My first attempts to create such SVG-based LQIP preview images were manual labor: I sketched major features of raster images with simple SVG shapes to learn how small the resulting SVG could become. I had ideas on how to automate generating SQIP images, but I didn’t get around to it.

Almost two years later, in September 2017, trivago enabled me to compile all my ideas and improvements for SQIP into a proper workflow. Efe Gürkan Yalaman then wrote SQIP in NodeJS so that it became easily useable: it is now available on Github and npmjs.com and is gaining popularity in the family of LQIP implementations.

SQIP’s rise in popularity is only possible thanks to the continuous efforts of browser vendors who have brought SVG support to all and improved its rendering performance. These are the shoulders of giants on which ideas like SQIP can stand on.

Bag o’ Tricks

SQIP aims to find a balance between keeping a small byte size and presenting good looking and valuable visual information. It makes use of Primitive to generate an SVG consisting of several simple shapes that approximate the main features visible inside an input image, then optimises the SVG using SVGO and finally adds a Gaussian Blur filter to it. This approach produces an SVG placeholder image commonly weighing in at only ~800-1000 bytes while looking smooth and providing sufficient visual information.

Another great side-effect of using SVG as the basis for image previews is that SVG is a plaintext asset and therefore benefits from compression by gzip, zopfli and brotli. Using these compression techniques cuts SQIP size down by half, reaching the minimum viable raster LQIP size of ~400-600 bytes while providing a superior user experience.

We can further increase the user experience of SQIP by ensuring that the high-resolution raster image that is being loaded in the background, be it synchronously or asynchronously, is encoded progressively. Taking control of the scan layer generation process of Progressive JPEGs enables us to granularly define how each incoming scan layer renders its information, making the transition from SQIP to incoming high-resolution raster image seamless.

The Future is Polygonal

SQIP will get even better in the future: the next upcoming improvement is to switch from circular SVG shapes to polygons. After some fine-tuning, this will enable SQIP-generated SVGs to consist of even fewer shapes while retaining decent proximity to the main visual features of an input image. Polygons may reduce SQIP’s average byte size by another ~5-10%.

A bigger step that’s a little further off into the future is rewriting Primitive, currently written in Golang, in Javascript and optimising it to achieve even closer visual proximity of main visual features of an input image with fewer shapes. Primitive was originally written with artistic usage in mind – gearing its output towards minimal byte size and maximum performance may reduce SQIP byte size even further.

Take-Aways

Image placeholders in SVG are ready for prime time thanks to browser support and good rendering performance. By automating SVG shape creation that mimics main features visible inside an image and compressing the result appropriately, we can achieve SVG-based image placeholders weighing in at only ~400 bytes. SQIP is a tool to make this process easy to integrate into your deployments.

Credits & Thanks: Michael Fogleman for creating Primitive, Kir Belevich et al for creating SVGO, trivago for providing the opportunity to write SQIP, Efe Gürkan Yalaman for writing SQIP in NodeJS, Sara Soueidan for her great work on SVG and José M. Pérez for his great LQIP article and graphics.