How to Use IntersectionObserver to Mark Current Scroll Progress

Follow me!

If you like this article, go ahead and follow me on Twitter:

Follow @getButterfly

Intersection

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:

<style>
html {
    scroll-behavior: smooth;
}

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

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

<script>
window.addEventListener('DOMContentLoaded', () => {
    const observer = new IntersectionObserver(entries => {
        entries.forEach(entry => {
            const id = entry.target.getAttribute('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) => {
        observer.observe(section);
    });
});
</script>

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

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

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

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

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.

👋 Added by Ciprian on Monday, September 28, 2020 in Blog. Last modified on Friday, March 12, 2021.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Privacy Policy