
aos.js is a lightweight, zero-dependency JavaScript library that triggers animations when elements enter the viewport during scroll.
The library provides fade, flip, slide, and zoom effects with full TypeScript support and weighs just 5.7KB.
It works across React, Vue, Angular, Astro, and vanilla JavaScript projects.
This is a modern TypeScript rewrite of the popular michalsnik/aos library. The rewrite delivers smaller bundle sizes and adds a proper destroy() method for cleanup.
Features:
- Smaller Bundle Size: 5.7KB core + 23.3KB CSS versus 14.7KB + 26.1KB in the original version.
- Custom Scroll Containers: Supports animating elements inside scrollable divs or sections.
- Modern Browser Optimizations: Built for current browsers with performance improvements.
See It In Action:
Example Use Cases:
- Landing Page Content Reveals: Gradually introduce sections, testimonials, or feature lists as users scroll down marketing pages.
- Portfolio Project Showcases: Animate project cards, images, or descriptions in creative or developer portfolios.
- Long-Form Article Enhancements: Add subtle animations to images, blockquotes, or statistics within blog posts or news articles.
- Dashboard Data Presentation: Reveal charts, graphs, or metrics in admin panels or analytics interfaces as users scroll.
How To Use It:
1. Install and import aos.js with NPM.
# NPM $ npm install @reimujs/aos
// Import the core library import AOS from "@reimujs/aos"; // Import the required stylesheet import "@reimujs/aos/dist/aos.css";
2. Or load the required JavaScript and CSS files directly in your HTML document.
// CDN <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@reimujs/aos/dist/aos.css" /> <script src="https://cdn.jsdelivr.net/npm/@reimujs/aos/dist/aos.umd.js"></script> // Local <link rel="stylesheet" href="/dist/aos.css" /> <script src="/dist/aos.umd.js"></script>
3. Initialize aos.js after the DOM loads:
AOS.init();
4. Add a scroll animation to any HTML element using the data-aos attribute. All available animation types:
Fade Animations:
fade– Simple fade infade-up– Fade in from bottomfade-down– Fade in from topfade-left– Fade in from rightfade-right– Fade in from leftfade-up-right– Diagonal fade from bottom-leftfade-up-left– Diagonal fade from bottom-rightfade-down-right– Diagonal fade from top-leftfade-down-left– Diagonal fade from top-right
Flip Animations:
flip-up– Flip along horizontal axis (bottom to top)flip-down– Flip along horizontal axis (top to bottom)flip-left– Flip along vertical axis (right to left)flip-right– Flip along vertical axis (left to right)
Slide Animations:
slide-up– Slide in from bottomslide-down– Slide in from topslide-left– Slide in from rightslide-right– Slide in from left
Zoom Animations:
zoom-in– Scale up from centerzoom-in-up– Scale up from bottomzoom-in-down– Scale up from topzoom-in-left– Scale up from rightzoom-in-right– Scale up from leftzoom-out– Scale down from centerzoom-out-up– Scale down moving upwardzoom-out-down– Scale down moving downwardzoom-out-left– Scale down moving leftwardzoom-out-right– Scale down moving rightward
<div data-aos="fade-up">Animate on scroll</div>
5. Apply easing to control animation acceleration:
Standard Easing:
linear– Constant speedease– Slow start, fast middle, slow endease-in– Slow start, acceleratesease-out– Fast start, deceleratesease-in-out– Slow start and end
Back Easing:
ease-in-back– Slight overshoot at startease-out-back– Slight overshoot at endease-in-out-back– Overshoot at both ends
Sine Easing:
ease-in-sine– Gentle accelerationease-out-sine– Gentle decelerationease-in-out-sine– Gentle curve both ways
Quadratic Easing:
ease-in-quad– Quadratic accelerationease-out-quad– Quadratic decelerationease-in-out-quad– Quadratic curve both ways
Cubic Easing:
ease-in-cubic– Cubic accelerationease-out-cubic– Cubic decelerationease-in-out-cubic– Cubic curve both ways
Quartic Easing:
ease-in-quart– Quartic accelerationease-out-quart– Quartic decelerationease-in-out-quart– Quartic curve both ways
<!-- Linear easing (constant speed) --> <div data-aos="fade-up" data-aos-easing="linear"> Constant speed animation </div>
6. Pass a configuration object to AOS.init() to define global defaults. We recommend setting these globally to maintain consistency across your UI.
- disable: Conditionally disable aos.js on specific devices or based on custom logic. Accepts boolean, string (‘phone’, ‘tablet’, ‘mobile’), expression, or function.
- startEvent: DOM event name that triggers AOS initialization. Default is ‘DOMContentLoaded’.
- initClassName: CSS class applied to all elements after AOS initializes. Default: ‘aos-init’.
- animatedClassName: CSS class applied when animation triggers. Default: ‘aos-animate’.
- useClassNames: When true, uses data-aos attribute value as additional class names.
- disableMutationObserver: Disables automatic detection of DOM changes. Set to true for manual control.
- debounceDelay: Milliseconds to wait before recalculating on window resize. Default: 50.
- throttleDelay: Milliseconds between scroll event processing. Default: 99.
- offset: Pixel distance from the anchor placement where animation triggers. Default: 120.
- delay: Milliseconds before animation starts after trigger. Range: 0-3000, step 50ms.
- duration: Milliseconds for animation to complete. Range: 0-3000, step 50ms.
- easing: Default easing function for all animations. Default: ‘ease’.
- once: When true, elements animate only once on scroll down. Default: false.
- mirror: When true, elements animate out when scrolling back up. Default: false.
- anchorPlacement: Defines which element position triggers the animation. Default: ‘top-bottom’.
- container: Scrollable container. Accepts CSS selector string or HTMLElement. Default: window.
AOS.init({
disable: false,
startEvent: "DOMContentLoaded",
initClassName: "aos-init",
animatedClassName: "aos-animate",
useClassNames: false,
disableMutationObserver: false,
debounceDelay: 50,
throttleDelay: 99,
offset: 120,
delay: 0,
duration: 400,
easing: "ease",
once: false,
mirror: false,
anchorPlacement: "top-bottom",
container: window,
});7. You can also override global settings per element using data-OPTION attributes:
<!-- Custom duration --> <div class="card" data-aos="fade-up" data-aos-duration="1500"> <h3>Slow Animation</h3> <code>data-aos-duration="1500"</code> </div> <!-- Custom offset --> <div class="card" data-aos="fade-up" data-aos-offset="300"> <h3>High Offset</h3> <code>data-aos-offset="300"</code> <p>Triggers later during scroll</p> </div> <!-- Animation delay --> <div class="card" data-aos="fade-up" data-aos-delay="500"> <h3>Delayed Start</h3> <code>data-aos-delay="500"</code> </div>
8. Trigger animations based on a different element’s scroll position:
The target element animates when the anchor element’s top edge reaches the viewport’s bottom edge.
<!-- Anchor element that triggers the animation --> <div class="trigger-element" id="trigger-left"> ANCHOR </div> <!-- Target element uses anchor's position --> <div class="animating-element" data-aos="fade-left" data-aos-anchor="#trigger-left" data-aos-anchor-placement="top-bottom"> TARGET </div>
9. API methods.
AOS.init(options?) – Initializes the library with optional configuration object. Call this once after DOM loads.
AOS.init({
duration: 800,
once: true
});
AOS.refresh() – Recalculates element positions after dynamic content changes. Use this when adding elements via JavaScript.
// After adding new elements to DOM
document.getElementById('container').innerHTML += '<div data-aos="fade-up">New content</div>';
AOS.refresh(); // Recalculate positionsAOS.refreshHard() – Forces complete reinitialization. This removes all event listeners and recreates them.
AOS.refreshHard(); // Full reset
AOS.destroy() – Removes all event listeners and observers. Use this for cleanup when unmounting components.
// Clean up before component unmounts AOS.destroy();
Framework Integration
Next.js:
"use client"; // Required for client-side code
import { useEffect } from "react";
import "@reimujs/aos/dist/aos.css";
export default function Page() {
useEffect(() => {
// Dynamic import prevents SSR issues
import("@reimujs/aos").then(({ default: AOS }) => {
AOS.init({
duration: 800,
once: true
});
});
}, []);
return (
<div data-aos="fade-up">
Animated content
</div>
);
}Vue 3 / Nuxt:
<script lang="ts" setup>
import { onMounted } from "vue";
import "@reimujs/aos/dist/aos.css";
onMounted(() => {
// Load AOS after component mounts
import("@reimujs/aos").then(({ default: AOS }) => {
AOS.init({
duration: 800
});
});
});
</script>
<template>
<div data-aos="fade-up">
Animated content
</div>
</template>Angular:
import { Component, Inject, PLATFORM_ID } from '@angular/core';
import { isPlatformBrowser } from '@angular/common';
import '@reimujs/aos/dist/aos.css';
@Component({
selector: 'app-root',
templateUrl: './app.component.html'
})
export class AppComponent {
constructor(@Inject(PLATFORM_ID) private platformId: Object) {
// Only run in browser environment
if (isPlatformBrowser(this.platformId)) {
import("@reimujs/aos").then(({ default: AOS }) => {
AOS.init({
duration: 800
});
});
}
}
}Astro:
---
// Import CSS in frontmatter
import "@reimujs/aos/dist/aos.css";
---
<div data-aos="fade-up">
Animated content
</div>
<script>
// Initialize AOS in client-side script
import AOS from "@reimujs/aos";
AOS.init({
duration: 800
});
</script>Alternatives:
- ScrollReveal: More granular control over animation sequences with a declarative API.
- Sal.js: Minimalist scroll animation library focused purely on performance. Sal.js has fewer animation options but weighs only 2.8KB.
- Best Scroll Animation Libraries: 10 best jQuery plugins and vanilla JavaScript animate on scroll (AOS) libraries that help developers to create awesome reveal animations on elements when they’re scrolled into view.
FAQs:
Q: Why aren’t my animations triggering on dynamically loaded content?
A: Call AOS.refresh() after injecting new DOM elements. The library needs to recalculate positions for newly added elements. If you’re using React or Vue, place the refresh call inside useEffect or onMounted hooks after the DOM update completes.
Q: How do I disable animations on mobile devices to improve performance?
A: Set disable: 'mobile' in the init options. This prevents aos.js from running on phones and tablets.
Q: Can I use aos.js inside a modal or scrollable div?
A: Yes. Set the container option to your scrollable element: AOS.init({ container: '.modal-content' }). You can pass either a CSS selector string or the HTMLElement reference directly.
Q: The animations feel too slow. How do I speed them up?
A: Reduce the duration value in milliseconds. The default is 400ms. Try duration: 200 for faster animations. You can set this globally in init options or per element using data-aos-duration="200".







