Front-End Performance Optimization: The Principle and Implementation of Image Lazy Loading

Front-End Performance Optimization: The Principle and Implementation of Image Lazy Loading

1. The Concept and Value of Lazy Loading

Lazy Loading is a technique that delays the loading of non-critical resources. For images, it means loading only the images within the current viewport, while images outside the viewport are loaded when the user scrolls to their position.
Core Value:

  • Reduces the number of HTTP requests on the first page load, improving the speed of the first screen rendering.
  • Saves user data (especially on mobile devices).
  • Reduces server load.

2. Implementation Principle

The key to lazy loading is determining whether an image has entered the viewport. Specific steps:

  1. Temporarily store the image's src attribute in the page (e.g., in data-src), and initially set src to empty or a placeholder image.
  2. Listen for scroll events (or use the Intersection Observer API) to calculate the relative position of the image to the viewport.
  3. When the image enters the viewport, assign the value of data-src to src, triggering the image load.

3. Traditional Implementation (Based on Scroll Events + getBoundingClientRect)

Step 1: HTML Structure Preparation

<img data-src="real-image-url" src="placeholder-or-empty-url" class="lazy-img" />

Step 2: Determine if the Image is in the Viewport

Use Element.getBoundingClientRect() to get the image's position relative to the top of the viewport:

function isInViewport(el) {
  const rect = el.getBoundingClientRect();
  return rect.top >= 0 && rect.top <= window.innerHeight;
}

Note: A buffer zone (e.g., loading 100px in advance) can be added to improve the experience:

rect.top <= window.innerHeight + 100;

Step 3: Scroll Listening and Loading

const lazyImages = document.querySelectorAll('.lazy-img');

function lazyLoad() {
  lazyImages.forEach(img => {
    if (img.dataset.src && isInViewport(img)) {
      img.src = img.dataset.src; // Trigger loading
      img.removeAttribute('data-src'); // Avoid duplicate loading
    }
  });
}

// Initial check once
lazyLoad();
// Debounce optimization for scrolling
window.addEventListener('scroll', throttle(lazyLoad, 200));

Debouncing/Throttling: Avoid performance issues caused by frequent triggering of scroll events.


4. Modern Implementation (Intersection Observer API)

Intersection Observer is a native browser API that efficiently listens to the intersection state of elements with the viewport, eliminating the need for manual position calculations.

Step 1: Create Observer

const observer = new IntersectionObserver((entries) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) { // Element enters the viewport
      const img = entry.target;
      img.src = img.dataset.src;
      observer.unobserve(img); // Stop observing loaded images
    }
  });
}, {
  rootMargin: '100px', // Trigger loading 100px in advance
});

Step 2: Bind Images That Need Lazy Loading

document.querySelectorAll('.lazy-img').forEach(img => {
  observer.observe(img);
});

Advantages:

  • Automatically manages intersection detection, no need to manually listen for scroll events.
  • Better performance, avoiding main thread blocking.

5. Optimization and Considerations

  1. Placeholder Strategy: Use minimal Base64 placeholder images or CSS background colors to avoid layout shifts.
  2. Responsive Images: When combining srcset and sizes attributes, the real URLs can be placed in data-srcset.
  3. SEO-Friendly: Ensure search engines can crawl the real image URLs (e.g., via <noscript> tag fallback).
  4. Error Handling: Listen for image load failure events and replace with a default image.

6. Summary

Lazy loading significantly improves page performance through "on-demand loading." The traditional approach relies on scroll events and position calculations, while the modern approach uses Intersection Observer for a more concise and efficient solution. In actual development, it is necessary to choose the implementation method based on specific scenarios and pay attention to compatibility and user experience optimization.