Intersection Observer for scroll to top buttons, or anything StiCKy

Raquel Fraktas
2 min readJul 7, 2022

At work, I was working on adding ‘back-to-top’ scroll button feature for when the user scrolls below the fold, and wants to get back to the top of the page without using their mouse and clicking through all that space on the scrollbar.

At first, I wanted to write a conditional JS statement that uses something like document.documentElement.offsetHeight > 1000 — but that doesn’t account for users who have BIG OLE screens. Using hardcoded values don’t account for this.

Instead, the lead developer introduced me to the Intersection Observer API. It is built into modern browsers (except for IE), that asynchronously observes changes in the intersection of a target element.

Here’s a great example of how you would use it.

const headerEl = document.querySelector('.header')
const sentinalEl = document.querySelector('.sentinal')
const handler = (entries) => {
console.log(entries)
// entries is an array of observed dom nodes
// we're only interested in the first one at [0]
// because that's our .sentinal node.
// Here observe whether or not that node is in the viewport
if (!entries[0].isIntersecting) {
headerEl.classList.add('enabled')
} else {
headerEl.classList.remove('enabled')
}
}
// create the observer
const observer = new window.IntersectionObserver(handler)
// give the observer some dom nodes to keep an eye on
observer.observe(sentinalEl)

The JS in the code pen asynchronously observes for changes in entries when there is a change in the screen, with the help of the Intersection Observer. It is called all the way in the end.

For this case, console.log(entries[0]) is fired when there is a scroll action is noticed. The isIntersecting returns false.

The isIntersecting property is a Boolean value which is true if the target element intersects with the intersection observer's root. If this is true, then, the IntersectionObserverEntry describes a transition into a state of intersection; if it's false, then you know the transition is from intersecting to not-intersecting.

If we were viewing the .sentinalEL target on the page, we are intersecting. Even if it is partial. If we scroll past it, it is not intersecting, creating a false value.

That’s all for now!

--

--