Dice UI

Scroll Spy

Automatically updates navigation links based on scroll position with support for nested sections and customizable behavior.

API

Installation

pnpm dlx shadcn@latest add @diceui/scroll-spy

Layout

Import the parts, and compose them together.

import {
  ScrollSpy,
  ScrollSpyNav,
  ScrollSpyLink,
  ScrollSpyViewport,
  ScrollSpySection,
} from "@/components/ui/scroll-spy";
 
return (
  <ScrollSpy>
    <ScrollSpyNav>
      <ScrollSpyLink />
    </ScrollSpyNav>
    <ScrollSpyViewport>
      <ScrollSpySection />
    </ScrollSpyViewport>
  </ScrollSpy>
)

Examples

Vertical Orientation

Set orientation="vertical" for content with vertical navigation.

Controlled State

Use the value and onValueChange props to control the active section externally.

Sticky Layout

For full-page scroll behavior, you can use a sticky positioned navigation sidebar that stays fixed while the content scrolls. This works with the default window scroll (no scrollContainer prop needed).

<ScrollSpy offset={100}>
  <ScrollSpyNav className="sticky top-20 h-fit">
    <ScrollSpyLink value="introduction">Introduction</ScrollSpyLink>
    <ScrollSpyLink value="getting-started">Getting Started</ScrollSpyLink>
    <ScrollSpyLink value="usage">Usage</ScrollSpyLink>
    <ScrollSpyLink value="api-reference">API Reference</ScrollSpyLink>
  </ScrollSpyNav>
 
  <ScrollSpyViewport>
    <ScrollSpySection value="introduction">
      <h2>Introduction</h2>
      <p>Your content here...</p>
    </ScrollSpySection>
    
    <ScrollSpySection value="getting-started">
      <h2>Getting Started</h2>
      <p>Your content here...</p>
    </ScrollSpySection>
    
    {/* More content sections */}
  </ScrollSpyViewport>
</ScrollSpy>

The key is to apply sticky top-[offset] to the ScrollSpyNav to keep the navigation visible as the page scrolls.

API Reference

ScrollSpy

The root component that manages scroll tracking and contains all ScrollSpy parts.

Prop

Type

Data AttributeValue
[data-orientation]"horizontal" | "vertical"

The navigation container component.

Prop

Type

Data AttributeValue
[data-orientation]"horizontal" | "vertical"

Navigation link that scrolls to a section.

Prop

Type

Data AttributeValue
[data-orientation]"horizontal" | "vertical"
[data-state]"active" | "inactive"

Viewport

The viewport container component for sections.

Prop

Type

Data AttributeValue
[data-orientation]"horizontal" | "vertical"

Section

Content section that gets tracked by the scroll spy.

Prop

Type

Data AttributeValue
[data-orientation]"horizontal" | "vertical"

Accessibility

Keyboard Shortcuts

The ScrollSpy component follows standard link navigation patterns:

KeyDescription
TabMove focus between navigation items.
EnterActivate the focused navigation item and scroll to the associated section.
SpaceActivate the focused navigation item and scroll to the associated section.

On this page