Lazy loading using Intersection Observer API

Good day, friends!

In this article, we will introduce the Intersection Observer API, a powerful new tool for lazily loading images and other elements on a page, supported by all modern browsers. We can use this tool to control the visibility of elements by defining preliminary or delayed loading of our DOM content.

As the web evolves, browsers support more and more new features and APIs, but something still hurts developers - DOM rendering. When we start developing a new application, create components, think over the HTML structure, style elements with CSS, we also think about the rendering process, how our page will look in general, and some other important things that require careful handling and affect application rendering.

This, in turn, affects how we create our elements, how our CSS will be organized, which libraries and frameworks will be used in the project, etc. This is why rendering is so important to developers.

One of the reasons for the popularity of the React library in the developer community is the fact that it uses a virtual DOM. In essence, this is a virtual representation of the real DOM, which you can control as you wish. After all the updates, the virtual DOM decides what changes need to be made to the original DOM, and makes these changes in a "seamless" way; there is no need to refresh the whole page when changing one element. This is one of the most significant advantages of React over other libraries and frameworks. DOM rendering is a costly (in terms of performance) task that React does just fine without any problems.

Some libraries and APIs allow us to improve the rendering of elements of our applications. We are going to get acquainted with one of them - the Intersection Observer API. But first, let's figure out what “lazy” image loading is.

How does lazy loading images work?


Lazy loading is one of the techniques for rendering page content. The concept of "lazy" loading is that instead of fully loading the page, we load only the necessary parts and postpone (delay) the loading of the remaining parts until they are needed by the user.

An example of a "lazy" download, which you probably heard about or that you have encountered, is the endless scrolling of the page. This works something like this: the user visits the page, the initial content is loaded, and only after the user scrolls the page down to the very end, the next portion of the content is loaded. In this case, there is no need to download all the content at once, which greatly facilitates the application.

If a “lazy” download serves to download only “user-generated” content, what is the opposite technique called? Some have heard of lazy loading before, but have not heard the opposite. The opposite of “lazy” loading is “energetic” loading (other options are impatient, fast-moving) - when all the content is immediately rendered.

Do you know that there are HTML attributes for lazy loading images? To use them, just add loading = “lazy” to the “img” or “iframe” element.



Using this technique, we get a lot of advantages: loading only the necessary resources reduces memory consumption and, ultimately, page load time. It also prevents the rendering of "unclaimed" code, which optimizes the application to work in low network bandwidth conditions. However, there are some drawbacks: this can affect the ranking of the page by search engines. In addition, it takes some time to choose the right library or API to work with.

Intersection Observer API


JavaScript is developing so fast that we get a new API almost every year. The main goal of the new APIs is to help create awesome applications and pages.

Intersection Observer is an API that allows you to monitor the visibility and position of DOM elements. The thing is that it works asynchronously, allowing you to smoothly (imperceptibly) change the visibility of elements, determining the preliminary or delayed loading of the content of our DOM.



A few years ago, we did not have an API or other tool for positioning and tracking an element. We had to write crazy and huge functions, create expensive (in terms of performance) methods that created more problems. Using the Intersection Observer API, we can do cool things like:

  • Endless page scrolling - create endless scrolling of tables, lists, grid containers, etc. It has never been so easy.
  • Images - why upload all images at once, when you can use the "lazy" download and display only the content that the user needs at the moment?
  • Monitoring elements - you can monitor the elements on the page. For example, you may receive messages about the closure of advertisements.

Here's where it all starts:

let myFirstObserver = new IntersectionObserver(callback, options)

We initialize the IntersectionObserver constructor and pass two parameters to it. The first parameter is a callback function, which is called in response to the intersection of our element with the viewport (i.e., when the element goes beyond the bounds of the viewport) or with another element. The options parameter is an object that controls the conditions for launching the callback function. This object has the following fields:

  • root - the parent element that serves as the viewport for the target element (for the element we are observing)
  • rootMargin - the outer margin around the root element (the values ​​of this field are similar to the margin values ​​in CSS). These values ​​can change for each side of the root before committing the intersection.
  • threshold - a number or an array of numbers that determines the percentage of intersection of the target element with the root element, at which the callback function is launched



Let's take a look at using the Intersection Observer API:

let options = {
    root: document.querySelector('.scroll-list'),
    rootMargin: '5px',
    threshold: 0.5
}

let myFirstObserver = new IntersectionObserver(elements => { elements.forEach(element => console.log('element', element)) }, options)

In order to start “monitoring” an element, you need to determine the target and call observer using the “observe” method, passing the target as a parameter:

let myDivTarget = document.querySelector('.header')

observer.observe(myDivTarget)

It should be remembered that all elements observed by the observer are rectangles. Irregularly shaped elements fit into the smallest rectangle.

What about browser support? Intersection Observer API is supported by all modern browsers such as Chrome, Edge, Firefox and Opera.



If you intend to work with a lot of data, for example, with a table containing a lot of information, the Intersection Observer API will be extremely useful for you.

One of the advantages of this API is that to solve such problems you no longer need to use any library.

Conclusion


We studied the Intersection Observer API and its use for lazy loading, observing the position of DOM elements, etc. Browsers support more and more APIs that reduce page rendering time, primarily for users with a slow connection, reducing the size of the project and displaying only relevant content.

From a translator: the article seemed to me insufficiently informative, so here are links to additional literature:


Thank you for attention.

All Articles