Animate On Scroll library for Svelte 5. Trigger CSS animations when elements scroll into view.
This package will give you an easy way to bring scroll-based animations to your Svelte applications using a simple and flexible API.
npm install svelte-aos
# or
pnpm add svelte-aos
# or
yarn add svelte-aos
// Import all animations
import 'svelte-aos/styles/full.css';
// Or import only what you need for smaller bundle
import 'svelte-aos/styles/base.css'; // Required
import 'svelte-aos/styles/fade.css'; // Only fade animations
Or in CSS:
/* Import all animations */
@import 'svelte-aos/styles/full.css';
/* Or import only what you need */
@import 'svelte-aos/styles/base.css'; /* Required */
@import 'svelte-aos/styles/fade.css'; /* Only fade animations */
<script>
import { aosAttachment, aosAction, AOS } from 'svelte-aos';
</script>
<AOS options={{ /* options */ }} />
<!-- Rest of your page or layout -->
Svelte 5.29+ (attachment):
<script>
import { aosAttachment } from 'svelte-aos';
</script>
<!-- Add data-aos only if you want the element to animate on first load when in viewport -->
<h2 data-aos="fade-up" {@attach aosAttachment({ animation: 'fade-up' })}>
AOS The Svelte Way
</h2>
Svelte 4.x to 5.28 (action):
<script>
import { aosAction } from 'svelte-aos';
</script>
<h2 data-aos="fade" use:aosAction={{ animation: 'fade' }}>
AOS The Svelte Way
</h2>
Opacity + optional translate
fade fade-up fade-down fade-left fade-right
fade-up-left fade-up-right fade-down-left fade-down-right
Scale + optional translate
zoom-in zoom-in-up zoom-in-down zoom-in-left zoom-in-right
zoom-out zoom-out-up zoom-out-down zoom-out-left zoom-out-right
3D rotation effects
flip-up flip-down flip-left flip-right
Translate from edge (no opacity)
slide-up slide-down slide-left slide-right
Customize each element with attachment or action parameters:
<!-- Svelte 5.29+ -->
<div data-aos="fade" {@attach aosAttachment({ animation: 'fade', duration: 1000 })}>
<!-- Svelte 4.x to 5.28 -->
<div data-aos="fade" use:aosAction={{ animation: 'fade', duration: 1000 }}>
<!-- Svelte 5.29+ -->
<div data-aos="fade" {@attach aosAttachment({ animation: 'fade', delay: 300 })}>
<!-- Svelte 4.x to 5.28 -->
<div data-aos="fade" use:aosAction={{ animation: 'fade', delay: 300 }}>
<!-- Svelte 5.29+ -->
<div data-aos="fade" {@attach aosAttachment({ animation: 'fade', easing: 'ease-out-back' })}>
<!-- Svelte 4.x to 5.28 -->
<div data-aos="fade" use:aosAction={{ animation: 'fade', easing: 'ease-out-back' }}>
<!-- Svelte 5.29+ -->
<div data-aos="fade" {@attach aosAttachment({ animation: 'fade', once: true })}>
<!-- Svelte 4.x to 5.28 -->
<div data-aos="fade" use:aosAction={{ animation: 'fade', once: true }}>
<div data-aos="fade-up" {@attach aosAttachment({ animation: 'fade-up', delay: 0 })}>First</div>
<div data-aos="fade-up" {@attach aosAttachment({ animation: 'fade-up', delay: 100 })}>Second</div>
<div data-aos="fade-up" {@attach aosAttachment({ animation: 'fade-up', delay: 200 })}>Third</div>
linear ease ease-in ease-out ease-in-out
ease-in-back ease-out-back ease-in-out-back
ease-in-sine ease-out-sine ease-in-out-sine
ease-in-quad ease-out-quad ease-in-out-quad
ease-in-cubic ease-out-cubic ease-in-out-cubic
ease-in-quart ease-out-quart ease-in-out-quart
<AOS /> ComponentAdd once at the top level of your page or layout. Configures global defaults.
<AOS
options={{
offset: 120, // Offset from viewport edge (px)
delay: 0, // Default delay before animation (ms)
duration: 400, // Default animation duration (ms)
easing: 'ease', // Default easing function
once: false, // Animate only once per element
anchorPlacement: 'top-bottom', // Which position triggers animation
disable: false, // Disable all animations
threshold: 0.1 // IntersectionObserver visibility threshold (0-1)
}}
/>
aosAttachment (Svelte 5.29+)Svelte 5 attachment for individual elements.
<div
data-aos="fade-up"
{@attach aosAttachment({
animation: 'fade-up',
delay: 150,
duration: 400,
once: true
})}
>
Animated
</div>
aosAction (Svelte 4.x to 5.28)Svelte action for individual elements.
<div
data-aos="fade-up"
use:aosAction={{
animation: 'fade-up',
delay: 150,
duration: 400,
once: true
}}
>
Animated
</div>
💡 Note: The
data-aosattribute is only needed if you want the element to animate on first page load when already visible in the viewport.
Disable all animations globally via the <AOS /> component:
<AOS
options={{
// Disable on specific device type
disable: 'mobile' // 'mobile' | 'phone' | 'tablet'
// Or disable entirely
disable: true
// Or use a custom function
disable: () => window.innerWidth < 768
}}
/>
Only import the animations you use to reduce bundle size:
| File | Animations | Required |
|---|---|---|
base.css |
Core setup, CSS variables, reduced motion | ✅ Yes |
fade.css |
fade, fade-up, fade-down, etc. | Optional |
zoom.css |
zoom-in, zoom-out variants | Optional |
flip.css |
flip-up, flip-down, etc. | Optional |
slide.css |
slide-up, slide-down, etc. | Optional |
easings.css |
Custom easing functions | Optional |
full.css |
Everything bundled | Convenience |
Example: Only fade animations with custom easings
import 'svelte-aos/styles/base.css';
import 'svelte-aos/styles/fade.css';
import 'svelte-aos/styles/easings.css';
<script>
import { aosAttachment, AOS } from 'svelte-aos';
import 'svelte-aos/styles/full.css';
</script>
<AOS config={{ once: true, disable: 'mobile' }} />
<main>
<section>
<h1 data-aos="fade-down" {@attach aosAttachment({ animation: 'fade-down' })}>Welcome</h1>
<p data-aos="fade-up" {@attach aosAttachment({ animation: 'fade-up', delay: 100 })}>
Scroll to see more
</p>
</section>
<section>
<div data-aos="fade-right" {@attach aosAttachment({ animation: 'fade-right' })}>Card 1</div>
<div data-aos="fade-right" {@attach aosAttachment({ animation: 'fade-right', delay: 100 })}>
Card 2
</div>
<div data-aos="fade-right" {@attach aosAttachment({ animation: 'fade-right', delay: 200 })}>
Card 3
</div>
</section>
</main>
<div data-aos="zoom-in" {@attach aosAttachment({ animation: 'zoom-in', easing: 'ease-out-back' })}>
Bouncy zoom effect
</div>
Contributions, issues, and feature requests are welcome! No formal contribution process is set up yet, but feel free to open issues or submit pull requests.
MIT