Implementing Lazy Loading for Images in JavaScript

Web performance is crucial for providing a smooth user experience, especially when it comes to loading media-rich websites. One effective technique to enhance performance is lazy loading. Lazy loading delays the loading of images until they are about to enter the user’s viewport, meaning they only load when they are actually needed. This reduces the initial load time of the page and conserves bandwidth by not loading offscreen images.

In this blog post, we’ll dive into a simple implementation of image lazy loading using vanilla JavaScript.

What is Lazy Loading?

Lazy loading is a design pattern that defers the loading of non-essential resources at the initial page load. Instead of loading all images at once, lazy loading waits until an image is just about to enter the viewport (the visible part of the web page) before loading it. This technique is particularly beneficial for pages with many images, as it improves both performance and user experience.

Implementing Image Lazy Loading

Let’s take a look at how we can implement lazy loading for images using a simple JavaScript script:

document.addEventListener("DOMContentLoaded", function() {


function lazyLoad() {

const lazyImages = document.querySelectorAll("img.lazy");
lazyImages.forEach(img => {
if (img.getBoundingClientRect().top < window.innerHeight && img.getBoundingClientRect().bottom > 0) {
img.src = img.dataset.src;
img.classList.remove("lazy");
}
});
}

lazyLoad(); // Initial load
window.addEventListener("scroll", lazyLoad);
});

Code Explanation

  1. Event Listener for DOMContentLoaded:
    • The script starts by adding an event listener to the DOMContentLoaded event. This event fires when the HTML document has been completely loaded and parsed, ensuring that our script runs after the DOM is ready.
    • Inside the event listener, we select all images with the class lazy using document.querySelectorAll("img.lazy"). These are the images that will be lazy-loaded.
  2. Lazy Loading Function:
    • We define a lazyLoad function that will handle the actual lazy loading of images.
    • The lazyLoad function loops through each image in the lazyImages NodeList. For each image, we use the getBoundingClientRect() method to get the image’s position relative to the viewport.
  3. Checking If Image is in Viewport:
    • The getBoundingClientRect() method returns an object with properties like top, bottom, left, right, etc., which describe the position of the element.
    • We check if the top of the image is within the viewport (img.getBoundingClientRect().top < window.innerHeight) and if the bottom of the image is not above the viewport (img.getBoundingClientRect().bottom > 0). This ensures the image is actually within the visible area of the window.
  4. Loading the Image:
    • If the image is within the viewport, we set its src attribute to the value stored in the data-src attribute. This triggers the loading of the image.
    • After the image is loaded, we remove the lazy class from the image to prevent it from being processed again.
  5. Initial Load and Scroll Event:
    • The lazyLoad function is called immediately after the DOM is ready to check if any images should be loaded right away (in case some are already in the viewport).
    • We also add an event listener to the scroll event to trigger lazyLoad every time the user scrolls. This ensures that images entering the viewport as the user scrolls down are loaded just in time.

Example HTML Structure

Here’s a simple example of how your HTML might look when using this lazy loading script:

<img class="lazy" data-src="image1.jpg" alt="Lazy Image 1">
<img class="lazy" data-src="image2.jpg" alt="Lazy Image 2">
  • data-src Attribute:
    • The data-src attribute holds the actual URL of the image. Initially, the src attribute is left blank or set to a placeholder, and the image is only loaded when it enters the viewport.
  • lazy Class:
    • The lazy class is used to identify images that should be lazy-loaded. This class is removed once the image has been loaded.

How Does This Improve Performance?

Lazy loading images can drastically reduce the initial load time of a webpage, especially if it contains a large number of images. By only loading images when they are needed (i.e., when they are about to be displayed), you reduce the amount of data that needs to be downloaded and processed when the page first loads. This not only improves the page load speed but also conserves bandwidth, which is particularly beneficial for users on slower connections or with data caps.

Advanced Considerations

  • Intersection Observer API:
    • For a more robust and efficient implementation, consider using the Intersection Observer API, which provides a way to asynchronously observe changes in the intersection of a target element with an ancestor element or with a top-level document’s viewport.
  • Fallbacks:
    • Consider adding a fallback mechanism for older browsers that do not support certain features used in your lazy loading script.
  • Placeholder Images:
    • You can improve the user experience by initially loading low-resolution placeholder images or using CSS to style a loading spinner while the actual image is loading.

Conclusion

Implementing lazy loading is a great way to optimize the performance of your web pages. By deferring the loading of images until they are about to be displayed, you can significantly reduce the initial load time and create a smoother user experience. The script provided in this post is a simple yet effective way to get started with lazy loading, but there are many ways to enhance it further depending on the needs of your project.