Everyone likes smooth loading. Lately I tried to make the background-image of the menu to load progressively(also to the cover if you view the blog on mobile).
If you take a look at how Medium does progressive image loading(or check out this article), you'll
notice that they use JavaScript and canvas to blur and store thumbnails. It seems a bit overkill to me. And when you need to do it on a background-image with background-position, things become even more complicated.
So I needed to figure out a simpler solution. Here's what I came up with:
Blur by default
As the article above mentioned:
By default, when a browser renders a small image scaled up, it applies a light blur effect to smooth the artefacts of the image. The effect can also be turned offfor images like QR codes.
But the default blur effect still feels blocky.
![]()
To make it smoother, I applied blur effect to the thumbnails while generating them, using GraphicsMagick for node:
1 |
const gm = require('gm') |
![]()
This looks acceptable to me. No need for a canvas or blur function. Already felt relieved! 😄
Layers
This method divides a component into four layers: container, thumbnail, mask and content.
- Container holds the full-size background image.
- Thumbnail holds the blur thumbnail, as
background-image. - Mask is a translucent black element, to darken the background.
- Everything else lives in the content layer.
Use z-index to separate the layers.
Image onload
When full-size image is loaded, hide the thumbnail. You can use this technic(with jQuery/Zepto):
1 |
var $container = $('.container') |
A live example:
No-js
No-js support is extremely easy. Just hide the thumbnail.
1 |
html.no-js .thumbnail { |
For my blog I also made a Sass Mixin/Extend with this method.