Lazy loading is a technique used to defer the loading of non-critical resources (such as images) at page load time. Instead, images are loaded only when they enter the viewport, improving performance and reducing initial page load time. In this tutorial, we’ll walk through the implementation of lazy loading for images using the IntersectionObserver API in JavaScript.

Prerequisites

Before getting started, ensure you have a basic understanding of HTML, CSS, and JavaScript.

Step 1: HTML Markup

First, include placeholder <img> tags in your HTML markup with the data-src attribute set to the actual image URL. The src attribute should be initially empty or set to a placeholder image.

HTML
<!-- Placeholder images with data-src attribute -->
<img class="lzy" data-src="image1.jpg" alt="Image 1">
<img class="lzy" data-src="image2.jpg" alt="Image 2">
<img class="lzy" data-src="image3.jpg" alt="Image 3">
<!-- Add more images as needed -->

Step 2: CSS (Optional)

You can optionally style the placeholder images with CSS to define their dimensions and appearance.

CSS
/* Style for lazy-loaded images */
.lzy {
width: 100%;
height: auto;
background-color: #f3f3f3; /* Placeholder background color */
}

Step 3: JavaScript Lazy Loading Script

Now, implement the lazy loading functionality using JavaScript and the IntersectionObserver API. This script will load images dynamically when they come into view.

JS
// Lazy load images after page load
window.onload = function() {
const images = document.querySelectorAll('.lzy');

const options = {
root: null, // viewport as root
rootMargin: '0px',
threshold: 0.5 // 50% of the image is in the viewport
};

const observer = new IntersectionObserver(function(entries, observer) {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
const src = img.getAttribute('data-src');
if (src) {
img.setAttribute('src', src);
img.removeAttribute('data-src');
observer.unobserve(img); // stop observing once loaded
}
}
});
}, options);

// Start observing each image
images.forEach(image => {
observer.observe(image);
});
};

Explanation

  • The script uses window.onload to ensure that it runs only after all resources (including images) have been loaded.
  • It selects all elements with the class .lzy (our placeholder images) and sets up an IntersectionObserver to monitor when they enter the viewport.
  • When an image comes into view (entry.isIntersecting), the data-src attribute is read to get the actual image URL (src).
  • The image src attribute is then set to the URL, loading the image.
  • Once loaded, the data-src attribute is removed, and the image is unobserved to stop further monitoring.

Conclusion

By implementing lazy loading using the IntersectionObserver API, you can significantly improve page performance by loading images only when needed. This technique helps reduce initial load times, especially for pages with lots of images or content below the fold.

Experiment with the provided code and adapt it to your specific project needs. Happy coding!