The BlurHash API provided by ServiceWorker.
https://github.com/3846masa/blurhash-sw
Add the following code to your ServiceWorker script.
// sw.js
importScripts('https://unpkg.com/[email protected]/dist/index.js');
blurhashSW({
routeUrl: '/.blurhash/:blurhash',
width: 32,
height: 32,
});
<script>
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/sw.js');
}
</script>
See also demo page.
Set the BlurHash URL as background-image
.
You should encode the BlurHash hash contained in the URL.
<img
src="https://source.unsplash.com/alY6_OpdwRQ/793x529"
alt="Shibuya 109"
width="793"
height="529"
style="
background-size: 100% 100%;
background-image: url(/.blurhash/LGBEE%2CIr.At8t8IU-%3DR%2BR6R4OrIo);
"
loading="lazy"
/>
Wrap the img element in the div element.
The BlurHash URL should be assigned as background-image
of the div element.
<div
style="
width: fit-content;
background-size: 100% 100%;
background-image: url(/.blurhash/LKF%23tH-psS%2C%3F3%3FoJWVNbIVs.%24*n%24);
"
>
<img
src="https://source.unsplash.com/7H77FWkK_x4/472x512"
alt="Tokyo tower"
width="472"
height="512"
style="
opacity: 0;
transition: ease-out 0.3s opacity;
"
onload="this.style.opacity=1"
loading="lazy"
/>
</div>
The BlurHash URL is not available until the ServiceWorker is ready.
Therefore, when visiting the site for the first time, background-image
cannot be loaded.
As a workaround, generate background-image
based on data-blurhash
when the ServiceWorker is ready.
navigator.serviceWorker
.register('/sw.js')
.then(() => navigator.serviceWorker.ready)
.then(() => {
const $elemList = document.querySelectorAll('[data-blurhash]');
for (const $elem of $elemList) {
const blurhash = $elem.dataset.blurhash;
$elem.style.backgroundSize = `100% 100%`;
$elem.style.backgroundImage = `url(/.blurhash/${encodeURIComponent(blurhash)})`;
}
});
<img
src="https://source.unsplash.com/HkGaG67usNE/597x398"
alt="Kinkaku-ji"
width="597"
height="398"
loading="lazy"
data-blurhash="L%C%zEXANengKnkCj]n$NMjXsoW?"
/>
<div
style="
width: fit-content;
"
data-blurhash="LmF~daR+NGWA_4RjRjWBkCadV@W;"
>
<img
src="https://source.unsplash.com/wPMvPMD9KBI/262x394"
alt="Himeji castle"
width="262"
height="394"
style="
opacity: 0;
transition: ease-out 0.3s opacity;
"
onload="this.style.opacity=1"
loading="lazy"
/>
</div>
PRs accepted.