# useScrollSpy

The id of the section the user is reading: the last of `ids` whose element has scrolled past the top of the viewport (plus `offset`). At the bottom of the page the last section is active, even if it is too short to reach the top. `null` before the first section, on the server, and during hydration.

Re-renders only when the active section changes. Sections are looked up by id on each scroll, so they can mount later.

## Import

```ts
import { useScrollSpy } from '@vincent.ri/react-tils'
// or only this hook
import { useScrollSpy } from '@vincent.ri/react-tils/useScrollSpy'
```

## Usage

```ts
const ids = ['install', 'usage', 'api']
const active = useScrollSpy(ids, { offset: 64 })
return (
  <nav>
    {ids.map((id) => (
      <a key={id} href={`#${id}`} aria-current={active === id ? 'location' : undefined}>{id}</a>
    ))}
  </nav>
)
```

## When to use it

Highlighting the current section in a table of contents, a docs sidebar, or step navigation on a long page.

## When not to

The sections scroll inside a container rather than the page; this follows the window. To know whether one element is on screen, use `useInView`.

## API

```ts
function useScrollSpy(ids: readonly string[], options?: ScrollSpyOptions): string | null
```

| Parameter | Description |
| --- | --- |
| `ids` | Element ids of the sections, in page order. |
| `options` | `offset`: height of a sticky header in pixels. Optional. |

**Returns** The active id, or `null`.

### Types

```ts
export type ScrollSpyOptions = {
  /** Distance in pixels from the top of the viewport to the line a section must cross to become active, e.g. a sticky header's height. Default `0`. */
  offset?: number;
};
```

## Browser support

Works in all modern browsers.

## Coming from another library?

Other libraries call this `useActiveSection`, `useScrollspy`.

---

266 B minified and brotlied
Source: https://github.com/vincentri/react-tils/blob/main/src/useScrollSpy.ts
Docs page: https://vincentri.github.io/react-tils/hooks/useScrollSpy/
Previous: [useScrollDirection](https://vincentri.github.io/react-tils/hooks/useScrollDirection.md)
Next: [useScrollProgress](https://vincentri.github.io/react-tils/hooks/useScrollProgress.md)
