Hone logo
Hone
Problems

Implement a Lazy Loading Image Handler with IntersectionObserver

This challenge will test your understanding of the IntersectionObserver API to implement an efficient lazy loading mechanism for images on a webpage. Lazy loading is crucial for improving website performance by deferring the loading of off-screen images until they are about to enter the viewport.

Problem Description

Your task is to create a JavaScript function that efficiently handles the loading of images using IntersectionObserver. When an image element is present in the DOM but its src attribute is not yet set (or is set to a placeholder), this function should observe the image. Once the image element enters the viewport, its src attribute should be updated with the actual image URL, triggering the browser to load it.

Key Requirements:

  1. Observer Initialization: Create an IntersectionObserver instance.
  2. Target Elements: The observer should target specific image elements. These elements will have an attribute (e.g., data-src) holding the actual image URL, and a placeholder src or no src initially.
  3. Callback Logic: The observer's callback function should:
    • Check if the target element is intersecting the viewport.
    • If intersecting, retrieve the actual image URL from the data-src attribute.
    • Set the src attribute of the image element to the retrieved URL.
    • Crucially, unobserve the image element once it has been loaded to prevent unnecessary future observations.
  4. Error Handling (Optional but Recommended): Consider how to handle potential image loading errors.

Expected Behavior:

  • Images initially outside the viewport should not load their actual content.
  • As an image scrolls into view, its src should be updated, and it should begin loading.
  • Once loaded and visible, the image should no longer be observed.

Edge Cases to Consider:

  • Images that are already within the viewport when the script runs.
  • Images that might fail to load.
  • Performance implications of observing too many elements.

Examples

Example 1: Basic Lazy Loading

Imagine the following HTML structure:

<img class="lazy-load" src="placeholder.gif" data-src="actual-image-1.jpg" alt="Image 1">
<img class="lazy-load" src="placeholder.gif" data-src="actual-image-2.jpg" alt="Image 2">

And the following JavaScript setup:

// Assume setupLazyLoadImages is called and the observer is configured
const lazyImages = document.querySelectorAll('.lazy-load');
setupLazyLoadImages(lazyImages);

Expected Outcome:

  • Initially, both images will display placeholder.gif.
  • When actual-image-1.jpg enters the viewport, its src will change to actual-image-1.jpg, and it will start loading.
  • When actual-image-2.jpg enters the viewport, its src will change to actual-image-2.jpg, and it will start loading.
  • Once each image has loaded and is visible, it should be unobserved.

Example 2: Image Already in Viewport

HTML:

<img class="lazy-load" src="placeholder.gif" data-src="already-visible-image.jpg" alt="Visible Image">

JavaScript:

// Assume setupLazyLoadImages is called and the observer is configured
const lazyImages = document.querySelectorAll('.lazy-load');
setupLazyLoadImages(lazyImages);

Expected Outcome:

  • If the already-visible-image.jpg is within the viewport when setupLazyLoadImages is executed, it should immediately have its src updated to already-visible-image.jpg and begin loading. It should then be unobserved.

Example 3: Handling Multiple Images

Imagine a page with many images, some of which will eventually enter the viewport.

HTML:

<!-- Many elements, including these lazy images -->
<div style="height: 1000px;">Scroll down</div>
<img class="lazy-load" src="placeholder.gif" data-src="scroll-image-1.jpg" alt="Scroll Image 1">
<div style="height: 1000px;">Scroll more</div>
<img class="lazy-load" src="placeholder.gif" data-src="scroll-image-2.jpg" alt="Scroll Image 2">

JavaScript:

// Assume setupLazyLoadImages is called and the observer is configured
const lazyImages = document.querySelectorAll('.lazy-load');
setupLazyLoadImages(lazyImages);

Expected Outcome:

  • scroll-image-1.jpg and scroll-image-2.jpg will not load until they scroll into view.
  • As the user scrolls, each image will load its respective data-src content when it becomes visible.
  • The observer should efficiently manage the loading of these images without impacting initial page load performance significantly.

Constraints

  • The solution must be implemented using native JavaScript. No external libraries are allowed for the core IntersectionObserver functionality.
  • The IntersectionObserver should be configured with an rootMargin of "0px" and an threshold of 0. This means an element is considered intersecting as soon as any part of it enters the viewport.
  • The actual image URL will be stored in a data-src attribute on the <img> element.
  • The placeholder image (or lack thereof) should not be a performance bottleneck.

Notes

  • The IntersectionObserver API is designed to be highly performant, so focus on correctly implementing the logic within the callback.
  • Consider how you will select the elements to be observed. A common approach is to use a specific class name.
  • Remember to clean up the observer by calling unobserve() on individual targets once their content has been loaded to ensure optimal performance.
  • You might want to add basic styling to the placeholder images to make it clear they are loading.
Loading editor...
javascript