Introduction

For a long time, since the advent of events, tracking the appearance of elements into the viewport has remained quite a useful activity.

Numerous applications have been using it for numerous purposes.

Most commonly, we've got lazy loading where images are loaded once they enter the viewport; infinite scrolling where content is dynamically generated once the page reaches its end; ad monitoring where calculations are made on how long and by how much proportions ad banners appear into the viewport.

But the list doesn't end here...

This idea is required even by something as simple as fixing an element once its top edge touches the top edge of the viewport, also known as sticky positioning.

Now, given that all these features have a huge amount of usage in applications, it shouldn't be surprising for you to know that some websites have also utilised all the four features shown above i.e loading images lazily, implementing infinite scrolling, having ad analytics libraries and sticky positioning some elements.

A complete combo! And what does this mean?

Well, it just means a lot of scroll listeners and a lot of calculations. That's it!

Going way deeper, it means poor application performance. But how can a bunch of simple scroll-based features degrade performance?

Akin to mousemove, touchmove, the scroll event fires at a high rate. This means that having even a single listener can potentially put a lot of load on the main thread. While this may not be an issue for just one listener which performs simple operations, imagine having four or five such listeners, each performing a heck of calculations.

You know where we're going!

Even to date, one of the biggest reasons for poor web application performance, especially laggy scrolls, is the poor handling of the scroll event. Developers impose strenous code to be executed on its occurence which, at the end of the day, tires out the main thread to do other things such as smooth CSS transitions.

But hey! This ain't the only pitfall of using scroll events to monitor elements coming into the viewport. We just haven't talked on the other side of the mirror i.e offsets, that bring with them another array full of problems.

Let's see a real-world example where offset calculations require quite tedious coding skills.

Suppose we have four ad banners to be monitored in our application, for how long they appear in the viewport. We'll start by calculating their offsets relative to the viewport and then lay out a for loop that checks all four of them at each scroll event, whether they've entered the viewport.

Once an image enters the viewport, we need to note down the time at which this happens and save that somewhere. This needs to be done for each of the four images. Finally, once the images leave the viewport, we once again note down the time at which this happens, subtract the previous time from this to obtain the time spent viewing the respective ad.

Sounds complex?

Well, it actually is complex, given that we have to maintain a global array to hold the entrance timestamps for each image and then monitor their appearance in and out of the viewport.

Definitely this ain't impossible to do with the offset calculations and the scroll event, but as you would agree not quite simple and efficient.

In this example, we would have to listen to the resize event as well to update our offsets likewise. Does this now sound a bit more complex?

Seeing all these inefficiencies and complexities imposed by continuously handling the scroll event just to do a simple thing i.e tracking elements' appearances, plus the popularity of the features that utilised it led to the developers of JavaScript to have a discussion.

What came as a result?

An API dedicated to tracking an element's appearance into and out of another element - the IntersectionObserver API.

Let's see what it is...