Nb. I originally wrote about this technique on my blog, and there are interactive examples there so if you find this interesting check it out! 😊
What is "Blurring Up" an image?
Sometimes big images take a bit too long to load, and it can ruin users' first impressions of a site.
"Blurring Up" an image involves initially rendering a very small image, scaling it up and then applying a Gaussian Blur.
This means you get a low-res blurry representation of the image while the full-size image loads, and you never have to worry about your users looking at blank boxes where images should be.
Implementing this in React
I wanted to create a neat and tidy reusable React Hook that I could use in various components for Blur Up image loading. Here is what I ended up with.
import React from 'react';
const useProgressiveImg = (lowQualitySrc, highQualitySrc) => {
const [src, setSrc] = React.useState(lowQualitySrc);
React.useEffect(() => {
setSrc(lowQualitySrc);
const img = new Image();
img.src = highQualitySrc;
img.onload = () => {
setSrc(highQualitySrc);
};
}, [lowQualitySrc, highQualitySrc]);
return [src, { blur: src === lowQualitySrc }];
};
export default useProgressiveImg;
This is a hook which accepts two arguments: a low-quality image src
, and a high-quality image src
.
By default this hook will return the src
of the low-quality pixelated image. Once the higher quality image has loaded, it will return that instead. This is achieved by adding an event listener to a new Image
object. The src
attribute of this Image
is set to the src
of our high quality image, so the event listener fires once the full-size image has loaded.
Once that image has loaded we switch from returning the pixelated image to returning the full-size image.
You may have also noticed that this hook returns a second value, which is an object containing a value I have called blur
. We can use this to know whether or not we need to "blur" the image. If the current src
being returned is that of the low-quality image, then we should blur the image, as that is the nasty pixelated one.
Usage
Here is an example of how to use this hook to get the desired "blur up" effect.
import React from "react";
import useProgressiveImg from "./useProgressiveImg";
const BlurredUpImage = () => {
const [src, { blur }] = useProgressiveImg(
"./tiny.jpg",
"./large.jpg"
);
return (
<img
src={src}
style={{
width: 200,
filter: blur
? "blur(20px)"
: "none",
transition: blur
? "none"
: "filter 0.3s ease-out"
}}
/>
)
}
In this example tiny.jpg
should be a very small version of the full-size image large.jpg
.
I have used inline styles here for simplicity's sake, but you could also use the blur
value to toggle a class, or pass it in as a prop to a styled component. The important thing here is that we are adding a CSS blur()
filter if the image hasn't loaded yet. The transition
makes the transition between the blurred and non-blurred states nice and smooth.
Thanks for reading
Let me know what you think of this handy hook in the comments.
Top comments (1)
Some comments may only be visible to logged-in visitors. Sign in to view all comments.