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.