Skip Navigation

Client-side decoding


Encodes the image with BlurHash and returns BlurHash as a string.

The default implementation of BlurHash expects the string to be decoded on the client-side, using a library like Wolt's blurhash or fast-blurhash.

This provides the most benefits, most notably including better color representation and smaller payload size, but requires the initial execution of such a library on the client-side, and thus is better used with a headless site or heavily makes use of client-side infinite scrolling/loading.

unlazy by Johann Schopplich is a great universal lazy loading library that supports client-side decoding of BlurHash hashes and works perfectly with this plugin. Read on, if you want to know how to implement decoding in a custom JS library.

An example implementation generating a placeholder image using the BlurHash string could look like this:

  data-blurhash="<?= $image->blurhash() ?>" // BlurHash string as attribute, to access via JS
  style="aspect-ratio: <?= $image->ratio() ?>;"> // Aspect ratio is required as canvas is absolutely positioned
import { decodeBlurHash } from 'fast-blurhash' //

const el = document.querySelector('div[data-blurhash]')
if (!el) return

const { blurhash } = el.dataset
if (!blurhash) return

const pixels = decodeBlurHash(blurhash, 32, 32)

const canvas = document.createElement('canvas')
canvas.width = 32
canvas.height = 32

const ctx = canvas.getContext('2d')
if (!ctx) return
const imageData = ctx.createImageData(32, 32)
ctx.putImageData(imageData, 0, 0)
div {
  position: relative;
  width: 400px;

canvas {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  height: 100%;
  width: 100%;

Details will vary in your implementation, as this e.g. does not feature lazy-loading capabilities, or you might want to use a different library, but the general idea is to use the BlurHash string as an attribute on an element, and then decode the BlurHash string on the client-side.