Creating a Sticky Table of Contents with Active Header Highlighting

Adding a table of contents to your blog or article can greatly improve the user experience. In this tutorial, we will learn how to create a sticky table of contents that dynamically lists the available headings on a page and highlights the active headings.

Prerequisites

To follow along with this tutorial, you should be familiar with React and React Hooks. You should also have Node.js installed on your system.

Setting Up the Project

First, we need to set up our project. We will create a new React app using the create-react-app command.

bash
npx create-react-app my-app

Next, we will install the required dependencies.

bash
npm install

Creating the Table of Contents Component

Now, let’s create our table of contents component. We will create a new file called TableOfContents.js in the src directory.

“`jsx
import React, { useState, useEffect } from ‘react’;

const TableOfContents = () => {
const [headings, setHeadings] = useState([]);

useEffect(() => {
const headings = document.querySelectorAll(‘h2, h3, h4’);
setHeadings(Array.from(headings));
}, []);

return (

    {headings.map((heading, index) => (

  • #${heading.id}}>{heading.textContent}
  • ))}

);
};

export default TableOfContents;
“`

In this code, we use the useState hook to store the headings in state. We then use the useEffect hook to get all the headings on the page and update the state.

Highlighting the Active Header

To highlight the active header, we will use the Intersection Observer API. We will create a new hook called useActiveHeader that will return the active header.

“`jsx
import { useState, useEffect } from ‘react’;

const useActiveHeader = () => {
const [activeHeader, setActiveHeader] = useState(null);

useEffect(() => {
const observer = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
setActiveHeader(entry.target);
}
});
}, { rootMargin: ‘-20% 0% -35% 0%’ });

const headings = document.querySelectorAll('h2, h3, h4');
headings.forEach((heading) => observer.observe(heading));

return () => observer.disconnect();

}, []);

return activeHeader;
};
“`

We then use this hook in our TableOfContents component to highlight the active header.

“`jsx
import React from ‘react’;
import useActiveHeader from ‘./useActiveHeader’;

const TableOfContents = () => {
const activeHeader = useActiveHeader();

return (

    {headings.map((heading, index) => (

  • #${heading.id}} style={{ fontWeight: activeHeader === heading ? ‘bold’ : ‘normal’ }}>
    {heading.textContent}
  • ))}

);
};
“`

Conclusion

In this tutorial, we learned how to create a sticky table of contents with active header highlighting. This feature can greatly improve the user experience of your blog or article.

Leave a Reply

Your email address will not be published. Required fields are marked *