Back to overview

Highlighting navigation items on scroll in React with IntersectionObserver

Compass lying on a physical map
| 2 min read
View count:

This week I was working on my personal website (, and I needed my navigation items to be highlighted when scrolling to the linked section. I found some solutions with a scroll listener, but none using the widely supported Intersection Observer (

So I decided to write the logic myself. What has to be done first, is referencing the <section>’s using React.useRef.

import * as React from "react";
const personalRef = React.useRef(null);
const portfolioRef = React.useRef(null);
const contactRef = React.useRef(null);

Now we have the reference to the <section>’s we can fire up the IntersectionObserver. I prefer to do this using the React.useEffect hook. The ref objects are added as dependencies, so we can reference these when they are ready. I use the 0.5 threshold, this will cause the observer to be triggered when the <section> is >50% visible. The navElement gets the navigation element which has a href pointing to the <section>’s id.

React.useEffect(() => {
let observer;
if (personalRef.current && portfolioRef.current && contactRef.current) {
const options = {
threshold: 0.5,
observer = new IntersectionObserver((entries, observer) => {
entries.forEach((entry) => {
const navElement = document.querySelector(
if (entry.isIntersecting) {
if (!navElement.classList.contains("active")) {
} else if (navElement.classList.contains("active")) {
}, options);
return () => observer.disconnect();
}, [personalRef, portfolioRef, contactRef]);

And that’s it! The active class will be added to the navigation element which points to the <>. By adding the return function at the end of the useEffect hook, we make sure the IntersectionObserver is cleaned up correctly.

Full code can be found on

Did you like this post? Check out my latest blog posts:

Person drawing flags on the ground
9 May 2024

Feature flags with Astro + Vercel Toolbar

5 min reading time

  • vercel
  • javascript
  • astro
Astral picture
29 Mar 2024

Astro DB: Migrating my analytics data from Vercel Postgres

5 min reading time

  • astro
  • database
  • vercel
  • postgres
  • libsql
Screenshot of an analytics dashboard
16 Jan 2024

Basic analytics with Vercel Postgres - Drizzle - Astro

10 min reading time

  • vercel
  • databases
  • typescript
  • astro