svelte-scroll-tracker is a lightweight Svelte component that tracks the scroll progress of an element within the viewport.
It generates a single CSS custom property, --scroll-progress representing the scroll progress from 0 to 1. You can then apply this value to various CSS animations, effects, or JavaScript logic.
See It In Action
Features
💨 Performance First: Utilizes a single IntersectionObserver to monitor element visibility. Scroll event handling is throttled with requestAnimationFrame for smooth updates.
🧩 Dependency-Free: Contains no external libraries, relying on native browser APIs and Svelte 5 reactivity. This keeps your project lean.
💻 Programmatic Access: Provides a children snippet slot. This slot gives you direct programmatic access to the progress value for JavaScript-based logic.
💡 CSS Variable Output: Exposes scroll progress via a --scroll-progress CSS custom property on the component’s root element. This simplifies integration with CSS-driven animations.
🎯 Conditional Updates: The CSS variable updates only when the tracked element is in view. This minimizes unnecessary DOM operations.
🔧 Customizable Thresholds: Offers startThreshold and endThreshold props. These props allow you to define the specific portion of the element’s visibility that maps to the 0-1 progress range.
Use Cases
- Scroll-Triggered Animations: Animate elements as they scroll into or through the viewport. You can link the
--scroll-progressvariable to CSS transforms, opacity, or other animatable properties. - Reading Progress Indicators: Create a visual bar or counter that shows how far a user has scrolled through an article or a long section of content.
- Parallax Effects: Implement parallax scrolling effects by adjusting the background position or movement speed of elements based on the scroll progress.
- Lazy Loading/Conditional Rendering: Show or hide content, or trigger data fetching, when an element reaches a certain scroll point within the viewport, using the programmatic
progressvalue. - Interactive Storytelling: Develop engaging narratives where elements or scenes change dynamically as the user scrolls, driven by the scroll progress.
Installation
npm install svelte-scroll-trackerUsage
You can utilize svelte-scroll-tracker in two primary ways: through its CSS variable or programmatically.
CSS Variable Usage
The component sets a CSS custom property --scroll-progress on its root element. This value ranges from 0 to 1 as you scroll.
<script lang="ts">
import ScrollTracker from 'svelte-scroll-tracker';
</script>
<ScrollTracker
startThreshold={0}
endThreshold={0.5}
debug={false}
>
<div style="height: 400px; border: 1px solid #ccc; background-color: #f0f0f0; display: flex; flex-direction: column; align-items: center; justify-content: center;">
<p>Scroll this element!</p>
<p>Current Progress: {Math.round(100 * ($css('--scroll-progress') || 0))}%</p>
<div style="width: 100%; background-color: #e0e0e0; margin-top: 10px;">
<div style="width: {($css('--scroll-progress') || 0) * 100}%; height: 20px; background-color: #4CAF50;"></div>
</div>
</div>
</ScrollTracker>In this example:
startThreshold={0}means progress tracking begins when the top of the element enters the bottom of the viewport.endThreshold={0.5}means progress tracking ends (reaches 1) when the element is scrolled halfway through the viewport.$css('--scroll-progress')accesses the CSS variable for display.
Programmatic Usage
For more complex logic, access the progress value directly using the children snippet slot.
<script lang="ts">
import ScrollTracker from 'svelte-scroll-tracker';
let showDynamicContent = false;
</script>
<ScrollTracker>
{#snippet children(progress)}
<div>This is static content.</div>
<p>Scroll Progress: {Math.round(progress * 100)}%</p>
{#if progress > 0.5}
{@const _ = (showDynamicContent = true)}
<div>This dynamic content appears when scroll progress is greater than 0.5.</div>
{/if}
<!-- You can also update reactive variables directly based on progress -->
<!-- $: showDynamicContent = progress > 0.5 -->
{/snippet}
</ScrollTracker>
{#if showDynamicContent}
<p style="margin-top: 20px; color: green;">Dynamic content section is now visible based on scroll!</p>
{/if}Here, the children snippet receives the progress (a number between 0 and 1) as an argument. You can use this value to conditionally render elements or trigger JavaScript functions.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| startThreshold | number | 0 | Defines when scroll progress mapping begins (0-1). 0 means the element’s top edge hits the viewport’s bottom edge. 1 means the element’s bottom edge hits the viewport’s bottom edge. |
| endThreshold | number | 0.5 | Defines when scroll progress mapping ends (0-1). 0.5 means the element’s center is at the viewport’s center. 1 means the element’s bottom edge hits the viewport’s top edge. |
| debug | boolean | false | Set to true to enable console logging for debugging purposes. |
Related Resources
- Svelte Motion: A Svelte animation library. While not strictly for scroll tracking, it can consume scroll progress values to create complex animations. Svelte Motion GitHub
- Intersection Observer API: The native browser API
svelte-scroll-trackeruses for performance. Understanding this API can help you grasp how the component works. MDN Web Docs: Intersection Observer API
FAQs
Q: How does svelte-scroll-tracker ensure performance?
A: It uses a single IntersectionObserver to detect viewport entry/exit and throttles scroll updates with requestAnimationFrame. It only updates the CSS variable when the element is visible.
Q: How do startThreshold and endThreshold work?
A: These props define the viewport-relative start and end points for tracking. startThreshold determines when progress begins (0), and endThreshold determines when it completes (1), based on how much of the element is visible or its position relative to the viewport.
Q: Is it possible to track the scroll progress of the entire page?
A: You can wrap your main page content or a full-height container within ScrollTracker to monitor overall page scroll progress relative to that container’s dimensions.
Q: Can I animate multiple properties with the --scroll-progress variable?
A: Yes, you can use the --scroll-progress CSS variable in multiple CSS rules to drive various animations or effects simultaneously.

