Detecting when an Element Becomes Fixed in CSS position:sticky with an Intersection Observer

Creating an element which would become fixed during scrolling has become very easy with position: sticky. However many times you will need to know when an element becomes sticky, or know when an element comes out of the sticky position. A good example would be a header that shrinks and becomes fixed during scrolling.

The new Intersection Observer API makes it possible to know whether an element is seen in the current viewport, or is hidden from the view. On similar grounds, it can also be used to know when the element comes in/out of sticky position. It is a bit hackish, but it does the trick :

  1. Add an element of height 1px before the element for which it is to known when it gets in/out of sticky position.
    Depending on case, the new element may need to be added after the required element.
  2. With the Intersection Observer API, observe the newly added element for its intersection with the screen.
  3. Depending on the intersectionRatio values, you may safely conclude whether the element is now sticky or not.

Demo

The demo shows a navigation bar that becomes fixed on scrolling. When fixed, a CSS class is added to the navbar that changes its background color and adds animation to the font. Again, when it comes out of sticky position, the class is removed.

Click here to see demo

Download codes for the demo

Sequence of Steps to be Followed

Below are the steps needed to be followed for the example of a onscroll fixed navigation bar. Your case may be different, but you may have to do something very similar to this.

  1. Adding a new element to HTML

    Before adding the new element :

    <body>
        <div id="logo-container"></div>
        <div id="nav-container">Navigation Container</div>
        <div id="main-container"></div>
    </body>
    

    After adding the new element #nav-container-top :

    <body>
        <div id="logo-container"></div>
        <div id="nav-container-top"></div>
        <div id="nav-container">Navigation Container</div>
        <div id="main-container"></div>
    </body>
    
  2. CSS

    #nav-container-top {
    	height: 1px;
    	background-color: blue;
    }
    
    #nav-container {
    	background-color: blue;
    	position: sticky;
    	top: 0;
    }
    
    .nav-container-sticky {
    	background-color: green !important;
    }
    

    The height of #nav-container-top has been set to 1px. The background color has been suitably adjusted. You can even specify visibility: hidden depending on your case.

    .nav-container-sticky class will be added to #nav-container when it becomes sticky.

  3. Observing the newly added element with Javascript

    Observe the newly added element to see when it becomes completely visible in the screen or gets completely hidden.

    var observer = new IntersectionObserver(function(entries) {
    	// no intersection with screen
    	if(entries[0].intersectionRatio === 0)
    		document.querySelector("#nav-container").classList.add("nav-container-sticky");
    	// fully intersects with screen
    	else if(entries[0].intersectionRatio === 1)
    		document.querySelector("#nav-container").classList.remove("nav-container-sticky");
    }, { threshold: [0,1] });
    
    observer.observe(document.querySelector("#nav-container-top"));
    

    Since the height of #nav-container-top is 1px, it being completely hidden would mean that #nav-container has now become sticky (with top as 0).

    Also when #nav-container-top becomes visible, it effectively means that #nav-container has now come out of sticky position.

Useful Resources

An event for CSS position:sticky

Loading Comments