useScroll
useScroll is used to create scroll-linked animations, like progress indicators and parallax effects.
Note: When scroll-linked animations are powered by the
scrollfunction frommotion, animations usingopacityortransformCSS properties can be hardware accelerated.
<script>
import { useScroll, useSpring } from '@humanspeak/svelte-motion'
const { scrollYProgress } = useScroll()
const scaleX = useSpring(scrollYProgress)
</script>
<div
style="position: fixed; top: 0; left: 0; right: 0; height: 5px;
background: #ff0088; transform-origin: left;
transform: scaleX({$scaleX});"
/><script>
import { useScroll, useSpring } from '@humanspeak/svelte-motion'
const { scrollYProgress } = useScroll()
const scaleX = useSpring(scrollYProgress)
</script>
<div
style="position: fixed; top: 0; left: 0; right: 0; height: 5px;
background: #ff0088; transform-origin: left;
transform: scaleX({$scaleX});"
/>Usage
Import
<script>
import { useScroll } from '@humanspeak/svelte-motion'
</script><script>
import { useScroll } from '@humanspeak/svelte-motion'
</script>useScroll returns four reactive Svelte stores:
| Store | Description |
|---|---|
scrollX | Horizontal scroll position in pixels |
scrollY | Vertical scroll position in pixels |
scrollXProgress | Horizontal scroll progress between 0 and 1 |
scrollYProgress | Vertical scroll progress between 0 and 1 |
Page scroll
By default, useScroll tracks the page scroll position:
<script>
import { useScroll, useSpring } from '@humanspeak/svelte-motion'
const { scrollYProgress } = useScroll()
const scaleX = useSpring(scrollYProgress)
</script>
<div
style="position: fixed; top: 0; left: 0; right: 0; height: 5px;
background: #ff0088; transform-origin: left;
transform: scaleX({$scaleX});"
/><script>
import { useScroll, useSpring } from '@humanspeak/svelte-motion'
const { scrollYProgress } = useScroll()
const scaleX = useSpring(scrollYProgress)
</script>
<div
style="position: fixed; top: 0; left: 0; right: 0; height: 5px;
background: #ff0088; transform-origin: left;
transform: scaleX({$scaleX});"
/>Element scroll
Track the scroll position of a specific scrollable element by passing it as the container:
<script>
import { useScroll } from '@humanspeak/svelte-motion'
let containerEl
const { scrollYProgress } = useScroll({ container: containerEl })
</script>
<div bind:this={containerEl} style="overflow-y: scroll; height: 300px;">
<!-- tall content -->
</div>
<div>Scroll progress: {$scrollYProgress}</div><script>
import { useScroll } from '@humanspeak/svelte-motion'
let containerEl
const { scrollYProgress } = useScroll({ container: containerEl })
</script>
<div bind:this={containerEl} style="overflow-y: scroll; height: 300px;">
<!-- tall content -->
</div>
<div>Scroll progress: {$scrollYProgress}</div>Element position
Track a target element’s position as it scrolls within its container (or the viewport):
<script>
import { useScroll } from '@humanspeak/svelte-motion'
let targetEl
const { scrollYProgress } = useScroll({ target: targetEl })
</script>
<div bind:this={targetEl}>
<div style="opacity: {$scrollYProgress}">
Fades in as you scroll to this element
</div>
</div><script>
import { useScroll } from '@humanspeak/svelte-motion'
let targetEl
const { scrollYProgress } = useScroll({ target: targetEl })
</script>
<div bind:this={targetEl}>
<div style="opacity: {$scrollYProgress}">
Fades in as you scroll to this element
</div>
</div>Scroll offsets
When tracking an element’s position, the offset option defines when the tracking starts and ends. Each offset is a pair of intersections — one for the target and one for the container:
<script>
import { useScroll } from '@humanspeak/svelte-motion'
let targetEl
// Start when target enters bottom of viewport,
// end when target reaches top of viewport
const { scrollYProgress } = useScroll({
target: targetEl,
offset: ['start end', 'end start']
})
</script><script>
import { useScroll } from '@humanspeak/svelte-motion'
let targetEl
// Start when target enters bottom of viewport,
// end when target reaches top of viewport
const { scrollYProgress } = useScroll({
target: targetEl,
offset: ['start end', 'end start']
})
</script>Named offset values:
| Value | Description |
|---|---|
"start" | Top edge of the element |
"center" | Center of the element |
"end" | Bottom edge of the element |
You can also use numbers (0 to 1) and pixel values ("100px").
Performance
Scroll animations work best with CSS properties that can be GPU-accelerated:
transform(translateX, translateY, scale, rotate)opacity
These properties don’t trigger layout or paint, so the browser can animate them on the compositor thread for smooth 60fps performance even during rapid scrolling.
Options
| Option | Type | Description |
|---|---|---|
container | HTMLElement | Scrollable element to track. Defaults to the page. |
target | HTMLElement | Target element to track position of within the container. |
offset | string[] | Array of scroll offsets defining when tracking starts and ends. |
axis | 'x' \| 'y' | Which axis to use for the single-axis progress callback. Defaults to 'y'. |
API Reference
Signature
useScroll(options?: UseScrollOptions): {
scrollX: Readable<number>
scrollY: Readable<number>
scrollXProgress: Readable<number>
scrollYProgress: Readable<number>
}useScroll(options?: UseScrollOptions): {
scrollX: Readable<number>
scrollY: Readable<number>
scrollXProgress: Readable<number>
scrollYProgress: Readable<number>
}Returns
An object with four Svelte Readable<number> stores.
See also
- Motion values overview — introduction to motion value stores
- useSpring — smooth scroll progress with spring physics
- useTransform — map scroll progress to visual ranges
- useMotionValueEvent — subscribe to scroll changes
Based on Motion’s useScroll API.