English | 简体中文
A smooth and customizable scroll-based slide animation component for Vue 3. Create engaging scroll experiences with dynamic scaling, translation, and occlusion effects.
- 🎯 Smooth Scroll Animations - Transform items as they scroll with elegant scaling and translation effects
- 📱 Direction Support - Both vertical and horizontal scrolling modes
- 🎨 Highly Customizable - Fine-tune animation parameters to match your design
- 🔄 Dynamic Item Management - Add or remove items on the fly
- 📐 Flexible Templates - Use generic or per-item slot templates
- 🚀 Performance Optimized - Efficient event handling and DOM updates
- 💅 TypeScript Support - Full type definitions included
- 🎭 Occlusion Effects - Optional lower item clipping for depth perception
npm install scroll-slidesyarn add scroll-slidespnpm add scroll-slides<script setup>
import { ScrollSlide } from 'scroll-slides';
</script>
<template>
<ScrollSlide
direction="vertical"
:item-count="10"
style="height: 600px; overflow-y: auto;"
>
<template #item="{ index }">
<div class="slide-item">
Slide {{ index + 1 }}
</div>
</template>
</ScrollSlide>
</template>
<style scoped>
.slide-item {
width: 100%;
height: 100px;
display: flex;
align-items: center;
justify-content: center;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border-radius: 15px;
color: white;
margin-bottom: 10px;
}
</style><template>
<ScrollSlide
direction="horizontal"
:item-count="15"
:scale-start-percent="0.95"
:translate-factor="50"
:spacer-enabled="true"
style="width: 100%; height: 200px; overflow-x: auto;"
>
<template #item="{ index }">
<div class="horizontal-item">
Item {{ index + 1 }}
</div>
</template>
</ScrollSlide>
</template>
<style scoped>
.horizontal-item {
width: 200px;
height: 120px;
margin-right: 15px;
background: #4CAF50;
border-radius: 10px;
display: flex;
justify-content: center;
align-items: center;
color: white;
}
</style>You can define unique content for each item using indexed slots:
<template>
<ScrollSlide direction="vertical" :item-count="3">
<template #item-0>
<div class="custom-item">🌸 First Item</div>
</template>
<template #item-1>
<div class="custom-item">🎨 Second Item</div>
</template>
<template #item-2>
<div class="custom-item">🚀 Third Item</div>
</template>
</ScrollSlide>
</template>| Prop | Type | Default | Description |
|---|---|---|---|
direction |
'vertical' | 'horizontal' |
'vertical' |
Scrolling direction |
itemCount |
number |
0 |
Total number of items in the list |
scaleRatio |
number |
0.7 |
Final scale of the item when it slides out (0-1) |
scaleStartPercent |
number |
0.8 |
Threshold percentage for scaling to start (0-1) |
translateFactor |
number |
100 |
Adjusts the displacement offset during slide-out |
spacerEnabled |
boolean |
false |
Adds a spacer at start to allow first item to scroll out |
occludeLowerItems |
boolean |
false |
Applies clip-path to prevent visual overlap |
Used when no specific item slot is defined:
<template #item="{ index }">
<!-- Your content here -->
<!-- index: number - The zero-based index of the current item -->
</template>Define unique content for specific items:
<template #item-0>
<!-- Content for first item -->
</template>
<template #item-1>
<!-- Content for second item -->
</template>Note: Indexed slots take priority over the generic #item slot.
Customize the spacer element (when spacerEnabled is true):
<template #spacer="{ size }">
<!-- size: number - The calculated size of the spacer in pixels -->
<div>Custom Spacer Content</div>
</template><ScrollSlide
:scale-ratio="0.9"
:scale-start-percent="0.95"
:translate-factor="20"
:item-count="10"
>
<template #item="{ index }">
<!-- Your content -->
</template>
</ScrollSlide><ScrollSlide
:scale-ratio="0.5"
:scale-start-percent="0.7"
:translate-factor="150"
:occlude-lower-items="true"
:item-count="10"
>
<template #item="{ index }">
<!-- Your content -->
</template>
</ScrollSlide><ScrollSlide
direction="horizontal"
:item-count="20"
:scale-ratio="0.85"
:scale-start-percent="0.9"
:translate-factor="30"
:spacer-enabled="true"
style="width: 100%; height: 250px; overflow-x: auto;"
>
<template #item="{ index }">
<div class="card">
Card {{ index + 1 }}
</div>
</template>
</ScrollSlide><script setup>
import { ref } from 'vue';
import { ScrollSlide } from 'scroll-slides';
const items = ref([1, 2, 3, 4, 5]);
const addItem = () => {
items.value.push(items.value.length + 1);
};
const removeItem = () => {
items.value.pop();
};
</script>
<template>
<div>
<button @click="addItem">Add Item</button>
<button @click="removeItem">Remove Item</button>
<ScrollSlide :item-count="items.length">
<template #item="{ index }">
<div>Item {{ items[index] }}</div>
</template>
</ScrollSlide>
</div>
</template><script setup>
import { ref, computed, onMounted, onUnmounted } from 'vue';
import { ScrollSlide } from 'scroll-slides';
const windowWidth = ref(window.innerWidth);
const direction = computed(() =>
windowWidth.value < 768 ? 'vertical' : 'horizontal'
);
const updateWidth = () => {
windowWidth.value = window.innerWidth;
};
onMounted(() => window.addEventListener('resize', updateWidth));
onUnmounted(() => window.removeEventListener('resize', updateWidth));
</script>
<template>
<ScrollSlide
:direction="direction"
:item-count="10"
:style="direction === 'vertical'
? 'height: 500px; overflow-y: auto;'
: 'width: 100%; overflow-x: auto;'"
>
<template #item="{ index }">
<!-- Responsive content -->
</template>
</ScrollSlide>
</template>-
Container Styling: Always set explicit dimensions and overflow properties on the ScrollSlide container:
<ScrollSlide style="height: 600px; overflow-y: auto;">
-
Item Spacing: Add margins to your item content, not the slot wrapper:
.my-item { margin-bottom: 10px; /* for vertical */ margin-right: 10px; /* for horizontal */ }
-
Performance: For large lists, consider using virtual scrolling techniques in combination with scroll-slides.
-
Z-Index: Items are automatically z-indexed in reverse order (first item on top). Plan your designs accordingly.
-
Spacer Usage: Enable
spacerEnabledwhen you want the first item to be able to scroll to the center/top of the viewport.
# Clone the repository
git clone https://github.com/agoudbg/scroll-slides.git
# Install dependencies
pnpm install
# Run development server
pnpm dev
# Build library
pnpm build
# Build demo
pnpm build:demoMIT License - see LICENSE file for details
Contributions, issues, and feature requests are welcome! Feel free to check the issues page.
agoudbg
- GitHub: @agoudbg
- Email: agoudbg@gmail.com
Give a ⭐️ if this project helped you!
Made with ❤️ using Vue 3 and TypeScript