Using IntersectionObserver and some extra DOM elements called sentinels to detect when an element becomes sticky.

I had a project where I needed to know when my <header> became sticky. In another project I needed to know when a user started to scroll so I could animate my fixed <header>.

Eric Bidelman wrote a great article on how to fire a custom event when position: sticky elements become fixed or when they stop sticking using IntersectionObserver. It introduces the notion of sentinels. Sentinels are dummy DOM elements to determine the scroll position. As Eric writes:

When a sentinel scrolls into the visible viewport, we know a header become fixed or stopped being sticky.

The use case Eric writes about was actually more robust than I needed. In addition, I was working on a WordPress site and struggling with the dynamic creation of the sentinels using Javascript. So, I hard-coded the sentinels in my theme’s header.php file. Unfortunately that meant adding empty <div>s to the DOM, but I’m not such a purist that I won’t add a little extraneous markup to achieve specific functionality.

I found a simpler implementation of the same concept by Nick McMillan. Because I had to support IE11, I modified his code to ES5 and included IntersectionObserver and forEach polyfills. Below is my Javascript.

const menuPrimary = document.getElementById( 'menu-primary' );
const sentinelPrimary = document.querySelector( '.sentinel-primary' );
function handlerPrimary( entriesPrimary ){
entriesPrimary.forEach( function( entry ){
if( entry.isIntersecting ){
menuPrimary.classList.remove( 'sticky' );
} else {
menuPrimary.classList.add( 'sticky' );
const observerPrimary = new window.IntersectionObserver( handlerPrimary );
observerPrimary.observe( sentinelPrimary );

You can see it in action on the FMC Sustainability website. There, I’m using two sentinels. The first sentinel hides the logo and the navigation in the blue band. The second sentinel detects when the primary navigation intersects the secondary navigation at which time they both become sticky.