Sling Academy
Home/JavaScript/Lazy-Load Images and Videos Using the JavaScript Intersection Observer

Lazy-Load Images and Videos Using the JavaScript Intersection Observer

Last updated: December 13, 2024

Lazy-loading is an important technique to improve web performance, especially in terms of loading times and resource management. With the Intersection Observer API, you can efficiently manage this process for images and videos, loading them only when they are in the viewport. This not only boosts the loading performance of your website but also conserves the user’s data by only downloading media when necessary.

What is Intersection Observer?

The Intersection Observer API is a relatively new addition to the web APIs that tracks changes in the intersection of a target element with an ancestor element or the top-level document's viewport. This means it can tell you when an element enters or exits the viewport, which is perfect for lazy-loading assets like images and videos.

Setting Up Intersection Observer

To get started, you'll need to understand the basics of setting up an Intersection Observer. The API follows the observer pattern and requires you to instantiate an IntersectionObserver with a callback function and an optional set of options.

const options = {
  root: null, // Specifying null makes it observe the viewport
  threshold: 0.1 // Fires callback when 10% of the target is in view
};

const observer = new IntersectionObserver((entries, observer) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      const lazyElement = entry.target;
      // Logic for loading element
    }
  });
}, options);

The options object allows you to define which part of the target must be visible for the observer's callback to be executed. A key parameter here is threshold, which indicates the percentage of the target's visibility necessary for a trigger.

Lazy-Loading Images

To lazy-load images, you first need to modify your HTML to support lazy-loading semantics. Typically, this involves using a placeholder or a low-resolution image initially and then loading the full image when required.


<img data-src="full-image.jpg" src="placeholder.jpg" alt="Image Description">

Next, you'll add the images to the observer's watch list:


const lazilyLoadImage = (img) => {
  const src = img.getAttribute('data-src');
  if (!src) {
    return;
  }

  img.src = src;
  img.removeAttribute('data-src');
};

const images = document.querySelectorAll('img[data-src]');
images.forEach(image => {
  observer.observe(image);
});

In the observer's callback, when an image is intersecting, the script replaces the src with a data-src attribute, loading the full image.

Lazy-Loading Videos

The process for videos is quite similar. You'll modify the HTML structure of the video to handle lazy-loading, potentially using a poster image or simply deferring its loading until it's in the viewport.


<video width="600" data-src="movie.mp4" controls poster="video-placeholder.jpg">
  Your browser does not support the video tag.
</video>

And add this video code to your observer:


const lazilyLoadVideo = (video) => {
  const src = video.getAttribute('data-src');
  if (!src) {
    return;
  }

  video.src = src;
  video.load();
  video.removeAttribute('data-src');
};

const videos = document.querySelectorAll('video[data-src]');
videos.forEach(video => {
  observer.observe(video);
});

When the Intersection Observer detects the video is within the viewport, the data-src attribute is swapped to src, and the video.load() method is called to start loading it.

Stopping Observations

After the observer has triggered and loaded each image or video, make sure to stop observing the respective element to prevent unnecessary computations:


entries.forEach(entry => {
  if (entry.isIntersecting) {
    observer.unobserve(entry.target);
  }
});

By unobserving elements once they are loaded, you free up system resources, as they no longer need to be monitored.

Conclusion

The Intersection Observer API provides a modern and efficient way to implement lazy-loading for images and videos. By loading media assets only when needed, it significantly enhances web performance and user experience. As you adopt this method into your projects, you will notice improvements in both loading speed and data usage, especially beneficial for users on mobile devices or slower connections.

Next Article: Trigger Animations When Elements Enter Viewport in JavaScript

Previous Article: Observe Element Visibility with the Intersection Observer API in JavaScript

Series: Web APIs – JavaScript Tutorials

JavaScript

You May Also Like

  • Handle Zoom and Scroll with the Visual Viewport API in JavaScript
  • Improve Security Posture Using JavaScript Trusted Types
  • Allow Seamless Device Switching Using JavaScript Remote Playback
  • Update Content Proactively with the JavaScript Push API
  • Simplify Tooltip and Dropdown Creation via JavaScript Popover API
  • Improve User Experience Through Performance Metrics in JavaScript
  • Coordinate Workers Using Channel Messaging in JavaScript
  • Exchange Data Between Iframes Using Channel Messaging in JavaScript
  • Manipulating Time Zones in JavaScript Without Libraries
  • Solving Simple Algebraic Equations Using JavaScript Math Functions
  • Emulating Traditional OOP Constructs with JavaScript Classes
  • Smoothing Out User Flows: Focus Management Techniques in JavaScript
  • Creating Dynamic Timers and Counters with JavaScript
  • Implement Old-School Data Fetching Using JavaScript XMLHttpRequest
  • Load Dynamic Content Without Reloading via XMLHttpRequest in JavaScript
  • Manage Error Handling and Timeouts Using XMLHttpRequest in JavaScript
  • Handle XML and JSON Responses via JavaScript XMLHttpRequest
  • Make AJAX Requests with XMLHttpRequest in JavaScript
  • Customize Subtitle Styling Using JavaScript WebVTT Integration