scroll-slides
v0.3.0
Published
English | [简体中文](./README_zh.md)
Readme
scroll-slides
English | 简体中文
A smooth and customizable scroll-based slide animation component for Vue 3. Create engaging scroll experiences with dynamic scaling, translation, and occlusion effects.
✨ Features
- 🎯 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
📦 Installation
npm install scroll-slidesyarn add scroll-slidespnpm add scroll-slides🚀 Quick Start
Basic Usage
<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>Horizontal Scrolling
<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>Independent Templates
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>📖 API Reference
Props
| 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 |
Slots
Default Item Slot
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>Indexed Item Slots
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.
Spacer 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>🎨 Customization Examples
Subtle Animation
<ScrollSlide
:scale-ratio="0.9"
:scale-start-percent="0.95"
:translate-factor="20"
:item-count="10"
>
<template #item="{ index }">
<!-- Your content -->
</template>
</ScrollSlide>Dramatic Effect
<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>Horizontal Card Carousel
<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>🔧 Advanced Usage
Dynamic Item Count
<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>Responsive Configuration
<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>💡 Tips & Best Practices
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.
🛠️ Development
# 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:demo📄 License
MIT License - see LICENSE file for details
🤝 Contributing
Contributions, issues, and feature requests are welcome! Feel free to check the issues page.
👤 Author
agoudbg
- GitHub: @agoudbg
- Email: [email protected]
🌟 Show Your Support
Give a ⭐️ if this project helped you!
Made with ❤️ using Vue 3 and TypeScript
