ScrollerBase
A low-level scroll position tracking primitive for scrollytelling. ScrollerBase uses IntersectionObserver to track which step is currently active and exposes bindable index and progress values that consumers use to drive visual changes.
This headless component uses a <div> element with an aria-label to create a labeled scrollable region for scrollytelling content.
Implementation Notes
- Uses
<div>element with classscroller-base - Tracks scroll position using IntersectionObserver
- Exposes current step index and overall progress as bindable values
- Steps are child elements; each child becomes a scrollytelling step
- Consumer uses index/progress to drive visual changes
- Offset controls where in the viewport a step triggers (0=top, 0.5=center, 1=bottom)
Props
children: slot (required) -- scrollable contentoffset: number (default: 0.5) -- viewport offset (0-1) where step triggers (0=top, 0.5=center, 1=bottom)index: number (bindable, default: 0) -- current active step indexprogress: number (bindable, default: 0) -- overall scroll progress (0-1)...restProps: Any additional HTML attributes
Usage
<ScrollerBase offset={0.5} bind:index bind:progress>
<div class="step">Step 1 content</div>
<div class="step">Step 2 content</div>
<div class="step">Step 3 content</div>
</ScrollerBase>
<ScrollerBase offset={0.3} bind:index>
<div class="step">
<h2>Introduction</h2>
<p>The story begins here.</p>
</div>
<div class="step">
<h2>Development</h2>
<p>The plot thickens.</p>
</div>
</ScrollerBase>
Keyboard Interactions
- Standard scroll behavior
- Tab navigates between focusable step content
ARIA
aria-labelfor the scrollable region- Steps should have appropriate roles as needed by the consumer
When to Use
- Use as the foundation for custom scrollytelling implementations
- Use when you need fine-grained control over scroll-driven interactions
- Use when building a custom scrollytelling layout that does not fit the Scroller foreground/background pattern
When Not to Use
- Do not use directly when you need the full scrollytelling experience with background/foreground composition -- use Scroller instead
- Do not use for simple scroll-triggered animations -- use IntersectionObserver directly or a simpler approach
Headless
This component provides a <div> element with IntersectionObserver-based scroll tracking, with zero visual styling. The consumer is responsible for all CSS including step layout, spacing, scroll snap, and any visual indicators of the current step.
Styles
The consumer provides all CSS styling. The component renders with a .scroller-base class for targeting. No default styles are included -- this is a fully headless component.
Testing
- Verify the component renders a
<div>element with classscroller-base - Verify
aria-labelis applied - Verify child steps are rendered correctly
- Verify index updates as steps enter the viewport offset
- Verify progress updates as the user scrolls
- Verify pass-through attributes are applied
Advice
- Designers: Plan step content with clear visual transitions in mind. Each step should represent a meaningful narrative beat. Consider how the viewport offset affects the reading experience.
- Developers: Always provide a descriptive
aria-labelfor the scrollable region. Use the bindableindexandprogressvalues to drive visual changes in sibling or parent components. Choose an appropriateoffsetvalue based on content type -- 0.5 (center) works well for most cases.
Related components
scroller— see components.tsvscroller-video— see components.tsvvisible— see components.tsv
References
- Reuters Graphics ScrollerBase
- IntersectionObserver API: https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver