Joe Bond

Creating a sticky header with the Intersection Observer API


I've been doing some testing with the intersection observer API, and it seems to be generally more performant than listening to a scroll listener.

In the simple performance tests I've seen that that scroll listeners versions of this same UI block the main thread for around .4ms over a 4 second period of scrolling down the page.

The intersection observer API version runs asynchronously, so it doesn't block the main thread at all, freeing up the CPU for other interactions. Fractions of a millisecond aren't a lot on their own, but if there are multiple items on a page we need to keep track of (like animations, a sticky navigation, or lazy loading images) it can lighten a potentially expensive process for the browser.

Creating an intersection observer is also pretty straightforward. Check the vanilla JS that's powering the CodePen at the bottom of the page for more details.

// Get all the elements you'll want to observe or update
const header = document.querySelector("#header")
const title = document.querySelector("#title")
const placeholder = document.querySelector("#placeholder")

// adds .sticky to the header
const slideInHeader = () => {
  }, 1000);

// removes .stkcy from the header
const slideOutHeader = () => {

// configuration for the observer
const config = {
  root: null

// create the observer
const observer = new IntersectionObserver(function (entries, self) {
  entries.forEach((entry) => {
    if (!entry.isIntersecting) slideInHeader();
    if (entry.isIntersecting) slideOutHeader(); 
}, config);

// observe the title to see when it's in view

See the Pen Sticky Header with Intersection Observer by Joseph Bond (@jcbond92) on CodePen.