This post was originally published at letsusetech.com.
Poorly loaded images can create an unpleasant browsing experience on your website. Not only is it painful to look at, but it also makes the website feel sluggish (even when everything else might be blazing fast).
By implementing lazy loading on images, you can optimize your images and make them load much quicker. Then you can use CSS and JavaScript to create a smooth image rendering process as the one shown in the following GIF:
Read on to learn how to implement advanced lazy loading techniques on your images for optimal performance and user experience.
How images load in websites by default
By default, the browser doesn’t do a great job at rendering images. While downloading an image, it shows a blank screen. This might confuse the visitor into thinking that nothing is happening.
Now, onto some demonstrations.
Create an empty folder on your computer. Inside this folder, create a file named index.html, open the file with a text editor, and paste the following markup:
lang="en">
Document
rel="stylesheet" href="style.css" />
class="grid">
src="./images/img-1.jpg" alt="">
src="./images/img-2.jpg" alt="">
src="./images/img-3.jpg" alt="">
src="./images/img-4.jpg" alt="">
There are sixteen images inside the
body {
margin: 0;
}
.grid {
display: grid;
grid-template-columns: 1fr 1fr;
}
img {
width: 100%;
aspect-ratio: 1/1;
display: block;
}
If you save the file and open index.html in your web browser, you should find a grid of images.
When you refresh the page, the images will load almost instantly. This is the case if you’re using a fast internet connection (plus the fact that you’re loading the images locally).
But if you were to go into the Network tab (in Devtool), enable the Slow 3G connection, and refresh the page, you’d notice that the images take longer to load. The browser also renders a white background while the image is loading:
This is because the browser downloaded all 16 images at once. Loading all sixteen images is needless and inefficient because the browser can only show four (or maybe six) images at a time on your page.
It slows the image rendering process, which is why you need to apply the lazy loading technique.
Implementing basic lazy loading on images
Lazy loading means you only load the images you can see, and as you scroll down the page, the browser will start to load more and more images. In other words, you’re loading the images “on demand”.
Go to all the tags in your markup and add the
loading = lazy
attribute to each of them; like so:
class="grid">
src="./images/img-1.jpg" alt="" loading="lazy">
Now if you refresh and check the Network tab again, you’d notice that the browser only downloads between six to ten images out of sixteen.
But as you scroll down the page, the browser will download more images, adding to the ones it already downloaded. This way, it downloads images only when they’re about to appear on the screen.
But lazy loading alone does not fix the problem
Yes, the browser will download fewer images thanks to lazy loading. But the images will still load slowly on slow networks, and the browser will show a giant white background in place of the images at first (which isn’t nice to see).
The solution to all of these issues is to perform lazy loading in a more advanced way. Instead of haphazard rendering, you’d make the images have a blurry background until the browser fully renders them.
By initially rendering a blurred version of the images, visitors can easily tell that the browser is attempting to render images there. This is much better than the white, blank screen it shows by default.
Advanced blurry loading
You need to create a blurred version of your images. Then you must tell the browser to show the blurred version until the actual images are viewable.
The first thing you need to do is create a super small version of all the images you’re rendering on the page. You can use any image editor on your computer to downsize each image or an online photo editor.
Next, inside index.html, create an
blur-mode
for each image. Afterward, move the image into the
. You need to set the small version of each image as the background image of the parent
:
class="grid">
class="blur-mode" style="background-image: url(images/img-1-small.jpg)">
src="images/img-1.jpg" alt="" loading="lazy">
To blur out the background image, you’re to add the following styles in the stylesheet file:
img {
/* Other CSS */
object-position: center;
object-fit: cover;
}
.blur-mode {
background-size: cover;
background-position: center;
}
If you changed the src
on an
tag to a non-existent image, the blurred version will appear:
One advantage of using this approach is that the downsized version you’re loading at the start is super small, so it won’t eat into the browser’s resources.
Use JavaScript to render images only when viewable
Now you may think that this is enough to get what you want, but it’s not.
Yes, the blurred images will show up on slow connections. But the actual images still load from top to bottom (and this doesn’t look good at all).
What you need to do is hide the image and only render it when the browser has fully downloaded it. To do that, we’re going to need to write some JavaScript.
Create a script.js file inside your website folder and include the following code:
const blurDivs = document.querySelectorAll(".blur-mode")
blurDivs.forEach((div) => {
const img = div.querySelector("img")
function loaded() {
div.classList.add("loaded")
}
if(img.complete) {
loaded()
} else {
img.addEventListener("load", loaded)
}
})
With the above code, you accessed all the images and called the loaded()
function on each image after the browser has completely downloaded it.
The loaded()
function adds the .loaded
class to the image, thereby rendering it on the page.
This is the style associated with the .loaded
class in style.css:
.blur-mode.loaded > img {
opacity: 1;
transition: opacity 200ms ease-in-out;
}
.blur-mode > img {
opacity: 0;
}
By initially setting opacity
to 0, you can slowly fade your image into the page when it loads fully in the browser. This is what we did in the first block of CSS above.
Adding CSS animation
One last thing you can do is add an animation indicating that the image is loading:
.blur-mode::before {
content: "";
position: absolute;
inset: 0;
animation: pulse 2.5s infinite;
}
Here you’re setting up a pulse animation that runs infinitely while the image is still loading. Here’s the keyframe definition:
@keyframes pulse {
0% {
background-color: rgba(255, 255, 255, 0)
}
50% {
background-color: rgba(255, 255, 255, 0.1)
}
100% {
background-color: rgba(255, 255, 255, 0)
}
}
The pulse animation is active for as long as the image is still being loaded by the browser. The animation gives the appearance that things are downloading.
Don’t forget to remove the animation when the image is fully loaded into the page:
.blur-mode.loaded::before {
content: none;
}
Now if you throttle your network speed to a Fast 3G and refresh your page, you’ll notice that the browser doesn’t give you that top-down loading of the images. Instead, it’s going to wait until the entire image is downloaded before fading it in.
Here’s a GIF showing the result:
Conclusion
Now you know how to implement advanced lazy loading on your images, you have everything you need to create a smooth image rendering experience for your users.
Thanks for following along and do have a great week.
Read Next
How to Create a Spotlight Card Hover Effect with Tailwind
CSS
Live Demo / Download — Welcome to this tutorial where we’ll take you on a journey to create…