I was recently working on a simple, single-page site with a fixed header containing in-page navigation links that needed to update on scroll. There are a ton of different ways to accomplish this, from adding unique classes to each section, to comparing the scroll position with section positions, but I wanted something a little more modern. Enter intersection observer!
MDN covers intersection observer in detail, but in a nutshell, it watches for an element to be visible in the viewport, and then fires a callback function. You can also add options, such as how much of the element needs to be visible before the function is called.
For example, if you wanted to watch for page sections to appear in the viewport, you would start with creating an observer:
const observer = new IntersectionObserver(callback, options);
Then add the callback function, which would be something like this:
const callback = (entries, observer) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
/* do something */
}
else {
/* undo above or do something else (optional) /*
}
});
};
Then add options, if needed:
const options = {
threshold: .3,
};
Finally, tell the observer what to watch (in this case, the page sections):
const sections = document.querySelectorAll("section");
sections.forEach((section) => {
observer.observe(section);
});
If you only need one, specific element to be watched, you can call the observer like this:
const element = document.querySelector(element);
observer.observe(element)
;
You can also set an element to be observed only once (for example, if you’re triggering an animation you only want to run once), by adding unobserve() to your callback, like so:
if (entry.isIntersecting) {
/* do something */
observer.unobserve(entry.target);
}
To see intersection observer in action for triggering animations and updating navigation links, visit this Codepen example