useScrollspy
Returns the id of the section being read, for a navigation or anything else that follows the scroll position.
Overview
useScrollspy(ids, options) observes the elements with the given ids and returns the id of the
one being read: the last, in document order, whose top has scrolled past a line near the bottom of
the scrolling area. It returns null before any has.
It is what Scrollspy runs on. Use it directly when the
active section drives something other than a Link, such as a heading, a progress indicator or a
navigation of your own.
It returns null on the server and on the first render in the browser, so the page hydrates
without a mismatch, and the active id from the first observation after that.
Basic usage
Reading: …
Introduction
This is some placeholder content for the useScrollspy example. The line above the box names the chapter being read. It is repeated in every chapter, to give the box enough to scroll.
This is some placeholder content for the useScrollspy example. The line above the box names the chapter being read. It is repeated in every chapter, to give the box enough to scroll.
Usage
This is some placeholder content for the useScrollspy example. The line above the box names the chapter being read. It is repeated in every chapter, to give the box enough to scroll.
This is some placeholder content for the useScrollspy example. The line above the box names the chapter being read. It is repeated in every chapter, to give the box enough to scroll.
Options
This is some placeholder content for the useScrollspy example. The line above the box names the chapter being read. It is repeated in every chapter, to give the box enough to scroll.
This is some placeholder content for the useScrollspy example. The line above the box names the chapter being read. It is repeated in every chapter, to give the box enough to scroll.
import { useRef } from 'react'
import { useScrollspy } from '@chassis-ui/react'
const chapters = [
{ id: 'hook-intro', title: 'Introduction' },
{ id: 'hook-usage', title: 'Usage' },
{ id: 'hook-options', title: 'Options' }
]
const text =
'This is some placeholder content for the useScrollspy example. The line above the box ' +
'names the chapter being read. It is repeated in every chapter, to give the box enough to ' +
'scroll.'
export const Example = () => {
const box = useRef<HTMLDivElement>(null)
const activeId = useScrollspy(
chapters.map((chapter) => chapter.id),
{ root: box }
)
const active = chapters.find((chapter) => chapter.id === activeId)
return (
<>
<p aria-live="polite">Reading: {active ? active.title : '…'}</p>
<div
ref={box}
role="region"
aria-label="Chapters"
tabIndex={0}
style={{ height: 200, overflowY: 'auto' }}
>
{chapters.map((chapter) => (
<div key={chapter.id} id={chapter.id}>
<h4>{chapter.title}</h4>
<p>{text}</p>
<p>{text}</p>
</div>
))}
</div>
</>
)
}API
useScrollspy
function useScrollspy(ids: readonly string[], options?: UseScrollspyOptions): string | null
interface UseScrollspyOptions {
root?: Element | RefObject<Element | null> | null
rootMargin?: string
}| Option | Type | Default | Description |
|---|---|---|---|
root | Element | RefObject<Element | null> | null | the viewport | The element that scrolls, or a ref to it. Only sections inside it are observed. |
rootMargin | string | '0px 0px -25%' | The margin around root, as IntersectionObserver takes it. Its bottom edge is the line a section's top passes to be active. |
A new array with the same ids doesn't observe again. Sections added, removed or renamed later are picked up; an id with no element is ignored.