How to Use IntersectionObserver to Mark Current Scroll Progress

on in Blog
Last modified on


Let’s say you have a list of anchors, or a table of contents, and this list is fixed on screen. Let’s say you want thislist to be fixed on screen and you want the titles to get highlighted as you scroll through the document.

You need a tiny bit of CSS:

html {
    scroll-behavior: smooth;

/* Basic, opinionated style */
.section-nav > a {
    color: #000000;
    font-weight: 700;

You also need a tiny bit of JavaScript, no dependencies:

window.addEventListener('DOMContentLoaded', () => {
    const observer = new IntersectionObserver(entries => {
        entries.forEach(entry => {
            const id ='id');
            if (entry.intersectionRatio > 0) {
                document.querySelector(`nav li a[href="#${id}"]`).parentElement.classList.add('active');
            } else {
                document.querySelector(`nav li a[href="#${id}"]`).parentElement.classList.remove('active');

    // Track all sections that have an `id` applied
    document.querySelectorAll('section[id]').forEach((section) => {

And then you need the HTML structure. Below is a placeholder structure:

<nav class="section-nav">
        <li><a href="#introduction">Introduction</a></li>
        <li><a href="#installation">Installation</a></li>

        <li><a href="#components">Components</a>
                <li><a href="#components--buttons">Buttons</a></li>
                <li><a href="#components--boxes">Boxes</a></li>
                <li><a href="#components--pills">Pills</a></li>

<section id="introduction">
    Introduction here
<section id="installation">
    Installation steps here
<section id="components--buttons">
    Button component here

Note how all the anchors match the section IDs. That’s it. Simple, fast and modern (using the IntersectionObserver API).

Use this for your documentation projects, how-to’s, frequently asked questions, tables of contents and more.

Photo by Deb Dowd on Unsplash.

Related posts