August 27, 2021

Loading Images With the “Blur Down” Technique

An experimental approach to deblurring images on load

A photo I took of Damon Albarn performing with the band 'Blur'

⚠️ Disclaimer

  1. Please avoid copying any code until reading the article in full. This is an experimental technique that comes with caveats.
  2. Examples on this page use a CSS-only Low Quality Image Placeholder (LQIP) generated via plaiceholder.co, but this isn't a hard requirement. You'll see the same with results strategies such as Base64 and more.
  3. Yes, I did just start an article about deblurring images on load by deblurring an image of Blur on load.

Earlier this week, I made the most of a long train journey to explore an idea; what if I could recreate a "bias lighting" effect for images on joebell.co.uk?

After a few hours of experimentation on a cortisol-inducing "premium" WiFi connection, I came up with a questionable but visually-impressive concoction of filter and backdrop-filter applied to a Low Quality Image Placeholder (LQIP). I quickly added a "blur up" transition on image load, and posted the results to twitter.

The "bias lighting" effect in action

Despite the tweet being well received, I decided against using the effect. Bright and colourful images looked great, but darker images – in my use-case, nearly all of my images – gave an effect more akin to a littered newspaper bleeding ink from the rain. A fun experiment, but not practical for my use-case.

Rereading the tweet every time a notification came through – let's be honest, we all do it – one thing started to stick out to me. The "blur up" on load transition was fine, but it felt unnatural. What would make it feel more photorealistic?

Let's imagine you're about to take a photograph of someone with an SLR camera. You look through the viewfinder to see the subject is out of focus; a blur. As you slowly start moving the focus ring, the blur morphs into a sharp image of your subject.

It got me wondering; could such an effect be achieved in CSS? An experiment that led to a wildly popular result and the unexpected existence of this post.

"Blur Up"

Before exploring alternatives, let's take a look at how the popular "blur up" technique works.

The transition occurs between 2 states, affecting 2 elements that are stacked on top of each other on the z-axis:

  1. Image not loaded
    1. LQIP – blurred to hide pixel detail and scaled to hide the fading edges.
    2. Image – visually hidden, with opacity set to 0.
  2. Image loaded
    1. LQIP – unchanged.
    2. Image – visible, with opacity set to 1.

The order or method of stacking doesn't matter too much, the effect remains the same. By transitioning only the opacity value of a single element, we can achieve a relatively nice-looking and high-performance transition.

However, the question still remains; could it be more photorealistic?

"Blur Down"

Let's flip the transition on its head. How could the image morph into the LQIP, like a camera when adjusting focus?

For the transition end – the full-size image – to look as close as possible to the transition start – the LQIP, the blur and scale styles need to be applied to both elements.

Similarly to the "blur up" transition, this occurs between 2 states, affecting 2 elements that are stacked on top of each other on the z-axis:

  1. Image not loaded
    1. LQIP – blurred to hide pixel detail and scaled to hide the fading edges.
    2. Image - visually hidden, with opacity set to 0, as well as a blur and scale that matches the LQIP.
  2. Image loaded
    1. LQIP – unchanged.
    2. Image – visible, with opacity set to 1, as well as deblurred and scaled down to its original size.

It doesn't offer the same "bokeh" effect that you would expect with an SLR camera, but it certainly feels more natural when compared side-by-side to the "blur up".

Caveats

One of the biggest issues with "blur up" is that an expensive property is being transitioned – filter.

When testing on my 2018 Macbook Pro, a relatively large drop in frame rate could be measured but not enough to be seen. It's safe to assume that users on low-end devices would not be so lucky.

Even with a last resort of using will-change to give the browser a hint, we cannot guarantee that filter will transition smoothly, and we cannot provide an escape hatch for those scenarios…

/**
 * We *can* respect a user's motion preference
 */
@media (prefers-reduced-motion: no-preference) {
  /**
   * We *cannot* be 100% sure that the browser can
   * transition `filter` effectively.
   * (this will always run, regardless)
   */
  @supports (transition-property: filter) {
    transition: 1.2s ease;
    transition-property: filter, opacity, transform;
  }
}

Which Blur Is Best?

It might appear odd that I would create the "blur down" effect, use it on my personal site, write a blog post about it and then advise you that you shouldn't use it; but that's exactly what's about to happen.

You probably shouldn't use "blur down".

If you do, you should at least strongly consider the caveats.

If the "blur up" transition is smooth for you, it's because:

  1. My personal site isn't very image-heavy.
  2. You're privileged enough to own a relatively high-end device with a GPU capable of transitioning filter.

The best blur transition is the one that will engage your users. It's down to you to decide whether visual quality is more important than performance.

Most of all, this transition was just an experiment – I was just having fun, I'm not advocating for a change!

Perhaps I'll experiment further and combine the "blur down" effect with Surma's "Animating a Blur" strategy to alleviate performance issues? Perhaps I'll even abandon the technique altogether?

Perhaps you will find something even better? Experiment! Blur the boundaries of CSS. You may be surprised with what you'll find.

––– views