Day 1: Intersection Observers

I intend to keep these posts as short as possible, so I'll get right into it.

Today I learned about intersection observers, Intersection Observer is a Web Api that allows you to know out when an element is visible on the browser screen relative to the window or any element you specify.

A very good use case for this would be when you want to lazy load images, you want to load the image only when that particular image element is on the page, intersection observers help you do this very easily. I created a code pen that demonstrates this and I’ll leave a link to that at the end of this post.

Let’s get to the fun part, writing some code:

To work with intersection observers, the first thing you want to do is select the element(s) to observe.

const myElement = document.querySelector('.my-el');

Now we've selected our element, the next thing we want to do is create an intersection observer object, creating this object takes two arguments.

  1. A callback function to be executed when our selected element comes into view or leaves the page
  2. An options object, more like a configuration for our observer
const observer = new IntersectionObserver(callback, options);

I'll talk about the options object first, this allows us to configure the behavior of our observer, it can have 3 properties, all optional.

const options = {
    root: null, /* by default this is set to the window, I'll talk about this in a bit */
    threshold: 0.25, /* any number from 0 - 1 */
    rootMargin: '15px' /* very similar to our regular margin property in css */
}

I'll explain these three properties a bit more.

  1. The root property specifies what you want the observed element to be relative to, by default it's the browser window, but you can also set it to any scrollable element on the DOM.
  2. The threshold property is any number from 0 - 1 that specifies how much of the observed element you want showing on the page before it can be considered as intersecting with the root. Say you want at least 25% of the element showing first, you can set the threshold to 0.25.
  3. The rootMargin is how much space you want to add or remove from the element, works just like regular margins. if you want at least 15px of the element to be showing before it can be considered as intersecting, you can set the rootMargin to 15px.

Now we've talked about the options, let's move to the callback function.

The callback function takes in two parameters,

  1. The entries, this is the list of all the elements that just got in view or are leaving the page.
  2. The observer, this is the observer Object we created, this gives access to all the methods, so we can do things like observe or unobserve elements, or even totally disconnect the observer.

Here's what that would look like.

const callback = (entries, observer) => {
  console.log(entries); //logging a list of currently observed items

  entries.forEach(entry => {
    console.log(entry);
    //each entry is an object with several properties, I'll briefly explain 3 of them

    console.log(entry.isIntersecting);
    //the isIntersecting property tells us if the element is in view or not

    console.log(entry.target);
    //the target property just points to the element itself, so its basically a DOM object

    console.log(entry.boundingClientRect);
    //this tells us the elements position relative to the root element we specified.

    /* Do something else on each entry */ 
  });

  const anotherElement = document.querySelector('.another-element');
   observer.observe(anotherElement) // we can observe another element with the observer parameter
   observer.unobserve(entries[0].target) // we can unobserve any element here also
   observer.disconnect(); // we can also totally disconnect the observer to stop watching all items completely
}

There's only one thing left we haven't done, probably the most important step, which is to actually observe our selected element, here's how that would look like.

observer.observe(myElement); // we're telling the observer to observe the element we selected at the beginning of the article.

If we had a NodeList as opposed to an actual DOM object, say we did a querySelectorAll as opposed to querySelector, here's how observing elements would look like.

const images = document.querySelectorAll('img');

images.forEach(image => {
   observer.observe(image);
});

And that's it, we've successfully learned how to use the IntersectionObserver, I'll do a quick recap so we don't miss the important parts.

  1. Create an observer object
  2. Use the observer object passing a callback function you want to run every time an element being watched enters or leaves the page.
  3. The callback function takes an entries parameter, each entry has a number of properties, the isIntersecting property being the most important tells us if the element is in view or not, the target property gives us access to the DOM element itself.
  4. Finally we watch our element(s) using the observe method on the observer we created.

Now here's a link to my codepen demonstrating how to use intersection observers to lazyload images.