Master Image Lazy Loading: From Scroll Events to IntersectionObserver

This article explains why loading all images in a long list hurts performance, presents step‑by‑step lazy‑loading techniques—including placeholder images, scroll calculations, getBoundingClientRect, and the modern IntersectionObserver API—provides full code samples, and discusses optimization tips for smoother front‑end experiences.

Tencent IMWeb Frontend Team
Tencent IMWeb Frontend Team
Tencent IMWeb Frontend Team
Master Image Lazy Loading: From Scroll Events to IntersectionObserver

Problem Statement

In a page with many list items each containing an image, loading all images at once slows rendering and wastes bandwidth, especially when only the first few are visible. Lazy loading loads images only when they enter the viewport.

Implementation Approach

1. Load a placeholder image by default. 2. Listen to the container’s scroll event. 3. Calculate the visible area and trigger loading when an image is about to appear. 4. Replace the src attribute with the real image URL stored in data-src.

Key Concepts

scrollTop – the container’s scroll offset. offsetTop – distance from the element to its nearest positioned ancestor. offsetHeight – element’s height including padding and border. An image should be loaded when scrollTop + offsetHeight >= offsetTop - offset.

Basic Code Example

/* CSS */
.container{
  width:200px;
  height:200px;
  position:relative;
  overflow-y:scroll;
}
.img-area{
  width:100px;
  height:100px;
}
<!-- HTML -->
<div class="container">
  <div class="img-area">
    <img class="pic" alt="loading"
         data-src="./img/img1.png"
         src="image-placeholder-logo.svg">
  </div>
  <!-- repeat img-area for other images -->
</div>
// JavaScript
var container = document.querySelector('.container');
container.onscroll = function(){
  checkImgs();
};

function isInSight(el){
  var sTop = container.scrollTop;
  var oHeight = container.offsetHeight;
  var oTop = el.offsetTop;
  return sTop + oHeight >= oTop;
}

function checkImgs(){
  var imgs = document.querySelectorAll('.pic');
  Array.from(imgs).forEach(function(el){
    if(isInSight(el)){
      loadImg(el);
    }
  });
}

function loadImg(el){
  var source = el.dataset.src;
  el.src = source;
}
checkImgs();

Optimizations

Throttle the scroll handler to reduce calls.

Mark already‑loaded images to avoid repeated checks.

Pre‑load with an offset and apply a fade‑in effect.

Alternative Using getBoundingClientRect

By comparing el.getBoundingClientRect().top with window.innerHeight, an image is considered visible when top <= innerHeight. This method avoids manual offset calculations.

IntersectionObserver Solution

The IntersectionObserver API automatically notifies when an element enters or leaves the viewport, eliminating manual scroll calculations. It is supported in modern browsers (Chrome 51+, Edge 15, Android 5+) and can be polyfilled for older versions.

var observer = new IntersectionObserver(function(entries){
  entries.forEach(function(entry){
    if(entry.isIntersecting){
      loadImg(entry.target);
    }
  });
});

document.querySelectorAll('.pic').forEach(function(img){
  observer.observe(img);
});

Infinite Scroll with IntersectionObserver

Observe a loading sentinel at the page bottom; when it becomes visible, fetch and prepend new items, then continue observing.

Conclusion

Image lazy loading significantly improves front‑end performance. Choosing between manual scroll calculations, getBoundingClientRect, or IntersectionObserver depends on project requirements and browser support.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

image-optimizationJavaScriptIntersectionObserverlazy loading
Tencent IMWeb Frontend Team
Written by

Tencent IMWeb Frontend Team

IMWeb Frontend Community gathering frontend development enthusiasts. Follow us for refined live courses by top experts, cutting‑edge technical posts, and to sharpen your frontend skills.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.