I have implemented a CSS based low quality image placeholder (lqip) system. What I implemented comes from this extensive blog post breaking it all down.
You can view a demo of it here:
How it works
The summary of how it works is that images are processed and a lqip style variable number is applied to each image, such as --lqip:-179989. This is a hash value that determines what the background gradient should look like, and it is accurate enough to the elements in the image.
Some fancy CSS decoding of this value is done to generate the background gradient of the image that then becomes the low quality image place holder.
I added it as part of my 11ty-image optimization build step. I made it work with remote images as well by retrieving the buffer created by 11ty fetch and passing that into the lqip generation function
I stripped as much of the code that wasn’t necessary for generating the lqip value. I even tried to just use the sharp dominant color instead of the Colorthief dominant color, but the gradients weren’t accurate so I kept this as well.
Caching
All of this processing, 11ty image + generating the lqip, starts to add up the more images there are on a site.
The first thing I did was implement a dictionary to check if an lqip value had been generated for an image already. This works well the same is used multiple times on a site, but it would still require to generate the lqip value each time.
After reading the 11ty fetch docs I found out that I could manually cache my own things. So I cached the generated lqip value.
With both of these optimizations, image processing is minimal. That being said, it is important to cache the .cache folder and the optimized images output within cloud cannon. You want these folders to persist between builds to reduce build times. My cache settings for my sites look like
node_modules,.cache,dist/assets/images
If you are using netlify, you can use the netlify plugin cache for caching.
Final thoughts
Overall this isn’t something that most people will notice. Internet speeds these days means that the lqip may show up for less than a second. My main reason for implementing it is just because I thought it was cool.
Code
Image optimization + lqip generation:
The lqip generation code:
The css: