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.