How to detect the top of a page using IntersectionObserver?

Just as the title says. I want to run some code when the user scrolls to the top of the page, and some other code when the user scrolls down. I can’t seem to find anything about it on the web.

I could observe an empty div at the top of the page and it does what I expect, but is it possible to do the same by observing the body instead?

Code that uses empty div
<body>
  <div id="page-top"></div>
  <!-- ... rest of content ... -->
</body>
const observer = new IntersectionObserver(function(entries) {
  if (entries[0].intersectionRatio <= 0) {
    // run some code when user scrolls away from the top
  } else {
    // run some code when user scrolls to the top
  }
});

observer.observe(document.getElementById('page-top'));
1 Like

If you’re trying to detect the top of the page, it might be more useful to add a scroll event listener to the window. That way, you needn’t add any special content to the html.

This snippet might help:

function scrollDetect() {
	let scrollY = window.scrollY;
	window.addEventListener('scroll',throttle(handleScroll,10));
  
	function handleScroll(e) {  
		if(window.scrollY > scrollY) {
			console.log('scrolling down');
		} else if (window.scrollY < scrollY){
			console.log('scrolling up');
		}
		if (window.scrollY === 0){
			console.log('at top'); 
		}    
		scrollY = window.scrollY;
	}
}

// https://www.sitepoint.com/throttle-scroll-events/
function throttle(fn, wait) {
	var time = Date.now();
  	return function(e) {      
		if ((time + wait - Date.now()) < 0) {
			fn(e);
			time = Date.now();
		}
	}
}

2 Likes

Yes, you can listen for scrolltop changes on the body like this

// Initial state
var scrollPos = 0;
// adding scroll event
window.addEventListener('scroll', function(){
  // detects new state and compares it with the new one
  if ((document.body.getBoundingClientRect()).top > scrollPos)
		document.getElementById('info-box').setAttribute('data-scroll-direction', 'UP');
	else
		document.getElementById('info-box').setAttribute('data-scroll-direction', 'DOWN');
	// saves the new position for iteration.
	scrollPos = (document.body.getBoundingClientRect()).top;
});

But this will trigger layout when calling getBoundingClientRect. If you experience layout thrashing, you should look into listening for keydown for pageUp/pageDown and wheel events.

https://javascript.info/onscroll