vue-scrollama
v3.0.1
Published
Easy scroll-driven interactions (scrollytelling) for Vue 3, powered by Scrollama
Downloads
991
Maintainers
Readme
Vue Scrollama
Easy scroll-driven interactions (scrollytelling) for Vue 3, powered by Scrollama.
Install
npm add vue-scrollamaQuickstart - Composable API
Use this when you want direct setup and lifecycle control.
If you provide onStepProgress, the composable auto-enables progress for you.
<template>
<div ref="container">
<div v-for="n in 3" :key="n" :data-step="n" class="step">
Step {{ n }}
</div>
</div>
</template>
<script setup>
import { ref } from 'vue'
import { useScrollama } from 'vue-scrollama'
const container = ref(null)
const { isReady, rebuild, resize, destroy } = useScrollama({
container,
stepSelector: '.step', // optional: defaults to direct container children
offset: 0.5,
progress: true,
onStepEnter({ element, index, direction }) {
console.log('enter', { stepId: element.dataset.step, index, direction })
},
onStepExit({ element, index, direction }) {
console.log('exit', { stepId: element.dataset.step, index, direction })
},
onStepProgress({ element, index, direction, progress }) {
console.log('progress', { stepId: element.dataset.step, index, direction, progress })
},
})
console.log(isReady.value) // false before mount, true after setup
// call rebuild() if step elements are added/removed dynamically
// call destroy() if you need manual early teardown
</script>Quickstart - Component API
Any direct child of <Scrollama> is treated as a step element.
The component API manages setup/teardown lifecycle for you.
<template>
<Scrollama @step-enter="onStepEnter" @step-exit="onStepExit" @step-progress="onStepProgress" :offset="0.5">
<div v-for="n in 3" :key="n" :data-step="n" class="step">
Step {{ n }}
</div>
</Scrollama>
</template>
<script setup>
import Scrollama from 'vue-scrollama'
function onStepEnter({ element, index, direction }) {
console.log('enter', { stepId: element.dataset.step, index, direction })
}
function onStepExit({ element, index, direction }) {
console.log('exit', { stepId: element.dataset.step, index, direction })
}
function onStepProgress({ element, index, direction, progress }) {
console.log('progress', { stepId: element.dataset.step, index, direction, progress })
}
</script>Nuxt / SSR
Scrollama requires browser DOM APIs, so render scroll stories client-side:
<template>
<ClientOnly>
<YourStory /> <!-- your component using useScrollama or <Scrollama> -->
</ClientOnly>
</template>useScrollama and <Scrollama> defer DOM access to onMounted, so they are SSR-safe to import, but story content should still be client-only to avoid hydration mismatch.
Examples
- Demo app:
apps/demo/ - Sticky graphic (pinned visual + scrolling steps):
apps/demo/components/StickyGraphicDemo.vue
API
useScrollama(options)
Required:
container: HTMLElement | Ref<HTMLElement | null>
Optional:
stepSelector?: string(defaults to direct container children)offset?: numberprogress?: boolean(auto-enabled whenonStepProgressis provided)once?: booleanthreshold?: numberdebug?: booleanroot?: string | HTMLElementonStepEnter?: (payload: { element, index, direction }) => voidonStepExit?: (payload: { element, index, direction }) => voidonStepProgress?: (payload: { element, index, direction, progress }) => void
Returns:
isReady: Readonly<Ref<boolean>>resize(): booleanrebuild(): booleandestroy(): void
useScrollama automatically calls resize() on window resize, orientation changes, and container size changes.
Component props
<Scrollama /> forwards props to scrollama.setup(options):
offset?: numberprogress?: booleanonce?: booleanthreshold?: numberdebug?: booleanroot?: string | HTMLElementstepSelector?: string
Reference: scrollama.setup(options)
Non-scrollama attributes (id, data-*, ARIA, classes, etc.) are forwarded to the root .scrollama__steps element.
Component events
step-enter:{ element, index, direction }step-exit:{ element, index, direction }step-progress:{ element, index, direction, progress }
Note: for the component API, progress tracking auto-enables when you listen to @step-progress.
Step element vs data-step
- A step element is the DOM element tracked by Scrollama.
data-stepis optional metadata you define on each step element.- Use
data-step(or anydata-*) when you want stable IDs/labels in handlers. - If you do not need custom metadata, rely on
indexfrom the payload.
Compatibility
- Module format: ESM only
- Node:
>=20 - Vue:
^3.5.0 - Scrollama:
~3.2.0 - Polyfill:
intersection-observernot required for modern browsers
Troubleshooting
No events fire
- Ensure steps are direct children of
<Scrollama>, or usestepSelectorwithuseScrollama - Ensure each step element has visible height
- Ensure container exists on mount (
refresolves to an element)
step-progress never fires
- Component API: attach
@step-progress - Composable API: provide
onStepProgress(auto-enables progress) or setprogress: trueexplicitly
Nuxt hydration mismatch
- Wrap the scroll story in
<ClientOnly>
Dynamic step content does not update
- Component API: rebuilds automatically when direct child step elements are added/removed
- Composable API: call
rebuild()after adding/removing step elements
Upgrade notes (v2 -> v3)
- Package is now ESM-only (CommonJS
require('vue-scrollama')is not supported) - Vue 3.5+ is required
- Scrollama upgraded to 3.x (
orderoption removed upstream) - For SSR/Nuxt, use
<ClientOnly>around stories
Releasing
- Release flow and pipeline details:
RELEASING.md
License
MIT
