a reasons

I have spent a lot of time with you and i realized one thing. I always being grateful. Either you are the thing that I should be grateful for or anything. All the little things you did for me are…

Smartphone

独家优惠奖金 100% 高达 1 BTC + 180 免费旋转




The Intersection Observer API explained.

A practical explanation on how the Intersection Observer works and how to leverage some of its different configurations and methods.

The Intersection Observer is a Web API that facilitates visibility tracking of elements within the viewport or its parent element(s). Some practical use cases could be lazy loading for images, dynamic imports based on interaction, scroll-spying navigation bars, among others. This API encapsulates a lot of logic that before its time, a developer would’ve had to build from scratch with several performance considerations in mind — believe me, mastering how to use the Intersection Observer is 100% worth it.

Before we start I want to acknowledge how was life before this API existed. We know that strategies like lazy loading or scroll-spying have existed for a while, and in order to achieve this, developers had to take into account several techniques and best practices to make it work smoothly and in a performant way. Some of the main complexities orbited around:

After jumping through some hoops, developers were able to achieve what the Intersection Observer seamlessly does. Now, don’t get me wrong, if you nail all of the above (and a couple more) you could create something as performant (or more) as the Intersection Observer. So if you’re up for the challenge, do it (let me know if this is something you’d be interested to read about in the comments).

But let’s not forget that this is adding a good amount of code to your codebase, it’s more code to be maintained and–hopefully–to be tested.

The Intersection Observer hides many implementation details and includes the different considerations we just talked about. Everything is boiled down into a class: IntersectionObserver.

By instantiating an IntersectionObserver you get an instance of an observer that knows how to detect intersections between a target element and its direct or indirect parent, being the browser viewport the highest level one (and default). All of this based on a configuration. This is when things start to get tricky… the configuration.

The Intersection Observer playground reacting to different configurations showing and hiding cards.

The scope of this tool is to showcase how a threshold: 0or threshold: 1 interacts with negative root margins (using either pixels or percentages). These terms might sound confusing so let’s dive in.

An instance of the IntersectionObserver that will be detecting intersections.

The element being observed by the said observer. The same observer can observe several targets.

🌳 Root configuration (root parameter)
The ancestor used to detect the intersection. In order to an intersection to happen the target needs to be a descendant of the root. By default the root is the viewport, as seen in the following image:

Picture this as sort of checkpoints along the area of the target. This checkpoints go from 0 to 1. Float values are valid. So as an example:

I want to highlight the “when the intersection of the target happens” part of both items above. The IntersectionObserver only triggers when there are intersections happening.

See the following image as a reference:

In this image there are two different Intersection Observer instances with two different configurations. The bottom left-hand side target will trigger an intersection as soon as it starts to peek, and the top right-hand target will trigger an intersection when it is completely visible.

Remember the CSS Box Model? Well this API applies a similar principle to the root. This provides the ability to customize where the intersections are detected. As an example let’s look at this image adding the following configuration: rootMargin: -100px 0px -250px 0px and how the intersection positions change:

Adding `rootMargin` delays the trigger of the Intersection Observer closer to the vertical center of the viewport.

A similar result can be achieved by using percentages instead of pixels:

Notice how using percentages now the height of the rootMargins depend on the height of the viewport. If the height of the root (viewport) is 900px then 20% would be 180px. This strategy is very useful if we want the rootMargin to be dynamic.

The minimum you need to do to use this API is to instantiate it and observe a target.

The callback is a good old JavaScript function that receives two parameters:

The callback will be called in two scenarios:

Whenever the callback gets called, an array of entries will be received and there are a several attributes that can be used. Nevertheless, let’s focus on two:

By understanding the different concepts we’ve just covered, you should be able to achieve a myriad of ideas and interactions. There are infinite combinations that can be done between the threshold, the rootMargin, and the implementation of the callback using isIntersecting and intersectionRatio.

I encourage you to play around with the tool mentioned above and try to find the different configurations that might work for your specific case. Here I’ll try to list some configurations I’ve used for different cases:

This configuration aims to solve the typical navigation that sets an active state to the items in it depending on the section being visible as the user scrolls:

This brief implementation will execute the callback every time a section touches the top edge of the viewport as the user scrolls up, therefore the rootMargin top is 0% and bottom is -100%. Now it’s on you to come up with a way to map the section to the navigation item to toggle its state.

Lazy loading images require a slightly different approach as requesting an image can take long depending on its weight. So we’d need to do a different configuration:

Notice how the rootMargin is now positive. Even though this tool doesn’t provide a way to make it happen, as we discussed above, this behaves similarly to the box model. Negative margins grow inward, positive margins grow outwards. This means that the images will trigger an intersection 50% outside of the viewport. See the following image as a reference:

The rootMargin 50% is a number that can be adjusted depending on the weight of the images or specific needs that you may have.

The approach for dynamic imports is similar to the lazy load of the images. Although, if code splitting is done right the files should be small if not tiny so the number could decrease from 50% to a 10%.

Using this configuration will allow you to detect the components that are about to be shown on the screen outside of the viewport. Giving you enough time to dynamically import it and then use it.

Thanks so much for the read. Please feel free to reach out if you have any questions or concerns. Happy to connect.

Add a comment

Related posts:

INSTALLMENTS

The Sprint Review is the event where the Scrum Team and the Stakeholders come together to inspect the outcome of the Sprint (aka the Increment that meets the Definition of Done), they collaborate on…

Why BEM is Amazing and How Do You Use It

When I started out in web development, I have started like most folks — naming css in the way it made the most sense for me. Because of this I would run into problems like having to think of the name…

House Robber

You are a professional robber planning to rob houses along a street. Each house has a certain amount of money stashed, the only constraint stopping you from robbing each of them is that adjacent…