
Scroll Reveal Libraries
- 1.4k installs
- 629 repo stars
- Updated November 20, 2025
- freshtechbro/claudedesignskills
scroll-reveal-libraries provides documented workflows for Simple scroll-triggered reveal animations using AOS (Animate On Scroll). Use this skill when building marketing pages, landing pages, or content-heavy sites req
About
The scroll-reveal-libraries skill simple scroll-triggered reveal animations using AOS Animate On Scroll Use this skill when building marketing pages landing pages or content-heavy sites requiring basic fade slide effects without complex animation orchestration Triggers on tasks involving scroll animations scroll-triggered reveals AOS simple animations or basic scroll effects Alternative to GSAP ScrollTrigger and Locomotive Scroll for simpler use cases Compare with motion-framer for React-specific animations Scroll Reveal Libraries Overview This skill covers AOS Animate On Scroll a lightweight CSS-driven library for scroll-triggered animations AOS excels at simple fade slide and zoom effects activated when elements enter the viewport Key Features Minimal Setup Single JavaScript file CSS Data Attribute API Configure animations in HTML Performance CSS-driven GPU-accelerated animations 50 Built-in Animations Fades slides zooms flips Framework Agnostic Works with vanilla JS React Vue etc When to Use Marketing landing pages with simple scroll effects Content-heavy sites blogs documentation Quick prototypes requiring scroll animations Projects where GSAP Framer Motion complexity isn't ne.
- **Minimal Setup**: Single JavaScript file + CSS
- **Data Attribute API**: Configure animations in HTML
- **Performance**: CSS-driven, GPU-accelerated animations
- **50+ Built-in Animations**: Fades, slides, zooms, flips
- **Framework Agnostic**: Works with vanilla JS, React, Vue, etc.
Scroll Reveal Libraries by the numbers
- 1,425 all-time installs (skills.sh)
- +93 installs in the week ending Jul 29, 2026 (Skillselion tracking)
- Ranked #165 of 1,039 Mobile Development skills by installs in the Skillselion catalog
- Security screen: LOW risk (skills.sh audit)
- Data as of Jul 31, 2026 (Skillselion catalog sync)
scroll-reveal-libraries capabilities & compatibility
- Capabilities
- **minimal setup**: single javascript file + css · **data attribute api**: configure animations in · **performance**: css driven, gpu accelerated ani · **50+ built in animations**: fades, slides, zoom · **framework agnostic**: works with vanilla js, r
- Use cases
- documentation
What scroll-reveal-libraries says it does
# Scroll Reveal Libraries ## Overview This skill covers AOS (Animate On Scroll), a lightweight CSS-driven library for scroll-triggered animations.
AOS excels at simple fade, slide, and zoom effects activated when elements enter the viewport.
npx skills add https://github.com/freshtechbro/claudedesignskills --skill scroll-reveal-librariesAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 1.4k |
|---|---|
| repo stars | ★ 629 |
| Security audit | 3 / 3 scanners passed |
| Last updated | November 20, 2025 |
| Repository | freshtechbro/claudedesignskills ↗ |
How do I use scroll-reveal-libraries for the task described in its SKILL.md triggers?
Simple scroll-triggered reveal animations using AOS (Animate On Scroll). Use this skill when building marketing pages, landing pages, or content-heavy sites requiring basic fade/slide effects without.
Who is it for?
Teams invoking scroll-reveal-libraries when the user request matches documented triggers and prerequisites.
Skip if: Skip when cached docs are missing, the request is a negative trigger, or another sibling skill owns the workflow.
When should I use this skill?
Simple scroll-triggered reveal animations using AOS (Animate On Scroll). Use this skill when building marketing pages, landing pages, or content-heavy sites requiring basic fade/slide effects without complex animation or
What you get
Step-by-step guidance grounded in scroll-reveal-libraries documentation and reference files.
- AOS-initialized page markup with scroll-triggered reveal attributes
Files
Scroll Reveal Libraries
Overview
This skill covers AOS (Animate On Scroll), a lightweight CSS-driven library for scroll-triggered animations. AOS excels at simple fade, slide, and zoom effects activated when elements enter the viewport.
Key Features:
- Minimal Setup: Single JavaScript file + CSS
- Data Attribute API: Configure animations in HTML
- Performance: CSS-driven, GPU-accelerated animations
- 50+ Built-in Animations: Fades, slides, zooms, flips
- Framework Agnostic: Works with vanilla JS, React, Vue, etc.
When to Use:
- Marketing/landing pages with simple scroll effects
- Content-heavy sites (blogs, documentation)
- Quick prototypes requiring scroll animations
- Projects where GSAP/Framer Motion complexity isn't needed
When NOT to Use:
- Complex animation timelines or orchestration → Use GSAP ScrollTrigger
- Physics-based animations → Use React Spring or Framer Motion
- Precise scroll-synced animations → Use GSAP ScrollTrigger
- Heavy interactive animations → Use Framer Motion
Core Concepts
Installation
CDN (Quickest):
<head>
<link rel="stylesheet" href="https://unpkg.com/aos@next/dist/aos.css" />
</head>
<body>
<!-- Content with data-aos attributes -->
<script src="https://unpkg.com/aos@next/dist/aos.js"></script>
<script>
AOS.init();
</script>
</body>NPM/Yarn (Recommended):
npm install aos@next
# or
yarn add aos@nextimport AOS from 'aos';
import 'aos/dist/aos.css';
AOS.init();Basic Usage
Apply animations using the data-aos attribute:
<!-- Fade in -->
<div data-aos="fade-in">Content</div>
<!-- Fade up -->
<div data-aos="fade-up">Content</div>
<!-- Slide from right -->
<div data-aos="slide-left">Content</div>
<!-- Zoom in -->
<div data-aos="zoom-in">Content</div>Configuration Options
Global Configuration:
AOS.init({
// Animation settings
duration: 800, // Animation duration (ms): 0-3000
delay: 0, // Delay before animation (ms): 0-3000
offset: 120, // Offset from trigger point (px)
easing: 'ease', // Easing function
once: false, // Animate only once (true) or every time (false)
mirror: false, // Animate out when scrolling past
// Placement
anchorPlacement: 'top-bottom', // Which position triggers animation
// Performance
disable: false, // Disable on mobile/tablet
startEvent: 'DOMContentLoaded', // Initialization event
debounceDelay: 50, // Window resize debounce
throttleDelay: 99 // Scroll throttle
});Per-Element Overrides:
<div
data-aos="fade-up"
data-aos-duration="1000"
data-aos-delay="200"
data-aos-offset="50"
data-aos-easing="ease-in-out"
data-aos-once="true"
data-aos-mirror="true"
data-aos-anchor-placement="center-bottom"
>
Custom configured element
</div>Common Patterns
1. Landing Page Hero Section
<section class="hero">
<!-- Staggered heading words -->
<h1
data-aos="fade-down"
data-aos-duration="800"
>
Welcome to the Future
</h1>
<!-- Delayed subheading -->
<p
data-aos="fade-up"
data-aos-delay="200"
data-aos-duration="600"
>
Transform your ideas into reality
</p>
<!-- CTA button -->
<button
data-aos="zoom-in"
data-aos-delay="400"
data-aos-duration="500"
>
Get Started
</button>
</section>2. Feature Cards Grid
<div class="features-grid">
<!-- Stagger cards with increasing delays -->
<div
class="feature-card"
data-aos="fade-up"
data-aos-duration="600"
data-aos-delay="0"
>
<h3>Feature 1</h3>
<p>Description...</p>
</div>
<div
class="feature-card"
data-aos="fade-up"
data-aos-duration="600"
data-aos-delay="100"
>
<h3>Feature 2</h3>
<p>Description...</p>
</div>
<div
class="feature-card"
data-aos="fade-up"
data-aos-duration="600"
data-aos-delay="200"
>
<h3>Feature 3</h3>
<p>Description...</p>
</div>
</div>3. Alternating Content Sections
<!-- Content from left -->
<div class="section">
<div
class="content"
data-aos="slide-right"
data-aos-duration="800"
>
<h2>Section Title</h2>
<p>Content slides in from left...</p>
</div>
<img
src="image1.jpg"
data-aos="fade-left"
data-aos-delay="200"
/>
</div>
<!-- Content from right -->
<div class="section reverse">
<img
src="image2.jpg"
data-aos="fade-right"
/>
<div
class="content"
data-aos="slide-left"
data-aos-duration="800"
data-aos-delay="200"
>
<h2>Section Title</h2>
<p>Content slides in from right...</p>
</div>
</div>4. Scroll-Triggered Testimonials
<div class="testimonials">
<div
class="testimonial"
data-aos="zoom-in"
data-aos-duration="500"
>
<blockquote>"Amazing product!"</blockquote>
<cite>- John Doe</cite>
</div>
<div
class="testimonial"
data-aos="zoom-in"
data-aos-duration="500"
data-aos-delay="100"
>
<blockquote>"Exceeded expectations"</blockquote>
<cite>- Jane Smith</cite>
</div>
</div>5. Custom Anchor Triggers
Trigger animations based on a different element's scroll position:
<!-- Fixed sidebar animates based on main content scroll -->
<div class="main-content">
<div id="trigger-point" data-aos-id="sidebar-trigger">
<!-- Content -->
</div>
</div>
<aside
class="sidebar"
data-aos="fade-left"
data-aos-anchor="#trigger-point"
>
Sidebar content
</aside>6. Sequential Animation Chain
<div class="animation-sequence">
<!-- Step 1: Heading -->
<h2
data-aos="fade-down"
data-aos-duration="600"
data-aos-delay="0"
>
Our Process
</h2>
<!-- Step 2: Description -->
<p
data-aos="fade-up"
data-aos-duration="600"
data-aos-delay="200"
>
Follow these simple steps
</p>
<!-- Step 3-5: Process cards -->
<div
class="process-step"
data-aos="flip-left"
data-aos-delay="400"
>
Step 1
</div>
<div
class="process-step"
data-aos="flip-left"
data-aos-delay="600"
>
Step 2
</div>
<div
class="process-step"
data-aos="flip-left"
data-aos-delay="800"
>
Step 3
</div>
</div>7. Image Gallery with Zoom Effects
<div class="gallery">
<img
src="photo1.jpg"
data-aos="zoom-in-up"
data-aos-duration="800"
/>
<img
src="photo2.jpg"
data-aos="zoom-in-up"
data-aos-duration="800"
data-aos-delay="100"
/>
<img
src="photo3.jpg"
data-aos="zoom-in-up"
data-aos-duration="800"
data-aos-delay="200"
/>
</div>Integration Patterns
React Integration
Basic Setup:
import { useEffect } from 'react';
import AOS from 'aos';
import 'aos/dist/aos.css';
function App() {
useEffect(() => {
AOS.init({
duration: 800,
once: true,
offset: 100
});
}, []);
return (
<div>
<h1 data-aos="fade-down">Welcome</h1>
<p data-aos="fade-up">Content here</p>
</div>
);
}Refreshing on Route Changes:
import { useEffect } from 'react';
import { useLocation } from 'react-router-dom';
import AOS from 'aos';
function App() {
const location = useLocation();
useEffect(() => {
AOS.init({ duration: 800 });
}, []);
// Refresh AOS on route change
useEffect(() => {
AOS.refresh();
}, [location]);
return <Routes>{/* routes */}</Routes>;
}Dynamic Content Updates:
import { useState, useEffect } from 'react';
import AOS from 'aos';
function DynamicList() {
const [items, setItems] = useState([]);
useEffect(() => {
AOS.init();
}, []);
const addItem = () => {
setItems([...items, { id: Date.now(), text: 'New Item' }]);
// Refresh AOS to detect new elements
setTimeout(() => AOS.refresh(), 50);
};
return (
<div>
<button onClick={addItem}>Add Item</button>
<ul>
{items.map((item) => (
<li key={item.id} data-aos="fade-in">
{item.text}
</li>
))}
</ul>
</div>
);
}Component Wrapper Pattern:
import AOS from 'aos';
import 'aos/dist/aos.css';
function AnimatedSection({ children, animation = "fade-up", delay = 0, ...props }) {
return (
<div
data-aos={animation}
data-aos-delay={delay}
{...props}
>
{children}
</div>
);
}
// Usage
<AnimatedSection animation="slide-right" delay={200}>
<h2>Animated Content</h2>
</AnimatedSection>Vue.js Integration
<template>
<div>
<h1 data-aos="fade-down">Vue + AOS</h1>
<div
v-for="(item, index) in items"
:key="item.id"
data-aos="fade-up"
:data-aos-delay="index * 100"
>
{{ item.text }}
</div>
</div>
</template>
<script>
import AOS from 'aos';
import 'aos/dist/aos.css';
export default {
mounted() {
AOS.init({ duration: 800 });
},
updated() {
// Refresh when component updates
this.$nextTick(() => {
AOS.refresh();
});
},
data() {
return {
items: [/*...*/]
};
}
};
</script>Next.js Integration
// pages/_app.js
import { useEffect } from 'react';
import AOS from 'aos';
import 'aos/dist/aos.css';
function MyApp({ Component, pageProps }) {
useEffect(() => {
AOS.init({
duration: 800,
once: true
});
}, []);
return <Component {...pageProps} />;
}
export default MyApp;// pages/index.js
export default function Home() {
return (
<main>
<h1 data-aos="fade-down">Next.js + AOS</h1>
<p data-aos="fade-up">Server-side rendered content with animations</p>
</main>
);
}Performance Optimization
1. Disable on Mobile Devices
AOS.init({
disable: 'mobile', // Disable on mobile
// Or use function for custom logic
disable: function() {
return window.innerWidth < 768;
}
});2. Use Once for Better Performance
AOS.init({
once: true, // Animate only once (better performance)
mirror: false // Don't animate out
});3. Optimize Throttle and Debounce
AOS.init({
throttleDelay: 99, // Scroll event throttle (default)
debounceDelay: 50 // Resize event debounce (default)
});4. Disable Mutation Observer for Static Content
AOS.init({
disableMutationObserver: true // Disable for fully static content
});5. Reduce Animation Complexity
<!-- Simpler animations perform better -->
<div data-aos="fade-in">Simple fade</div>
<!-- Complex animations may cause jank -->
<div data-aos="flip-left">Complex flip</div>6. Use RequestIdleCallback for Initialization
if ('requestIdleCallback' in window) {
requestIdleCallback(() => {
AOS.init({ duration: 800 });
});
} else {
AOS.init({ duration: 800 });
}Common Pitfalls
1. Forgetting to Refresh After DOM Changes
Problem: New elements don't animate after being added dynamically.
Solution: Call AOS.refresh() or AOS.refreshHard():
// After adding elements to DOM
const newElement = document.createElement('div');
newElement.setAttribute('data-aos', 'fade-in');
container.appendChild(newElement);
// Refresh AOS
AOS.refresh(); // Recalculate positions
// or
AOS.refreshHard(); // Reinitialize completely2. Animations Not Working in React
Problem: AOS doesn't detect elements on first render or route changes.
Solution: Initialize in useEffect and refresh on route/content changes:
useEffect(() => {
AOS.init();
return () => AOS.refresh(); // Cleanup
}, []);
useEffect(() => {
AOS.refresh(); // Refresh on route change
}, [location.pathname]);3. Scroll Performance Issues
Problem: Page scrolling feels janky with many animated elements.
Solution: Reduce animated elements and use once: true:
AOS.init({
once: true, // Animate only once
disable: window.innerWidth < 768 // Disable on mobile
});4. CSS Conflicts
Problem: Custom CSS interferes with AOS animations.
Solution: Use more specific selectors and avoid !important:
/* Bad: Conflicts with AOS */
div {
opacity: 1 !important;
}
/* Good: Specific selector */
.my-content > div {
/* styles */
}5. Anchor Placement Confusion
Problem: Animations trigger at unexpected scroll positions.
Solution: Understand anchor placement options:
// Triggers when element's top hits viewport bottom
data-aos-anchor-placement="top-bottom"
// Triggers when element's center hits viewport center
data-aos-anchor-placement="center-center"
// Triggers when element's bottom hits viewport top
data-aos-anchor-placement="bottom-top"6. Duration/Delay Limits
Problem: Values above 3000ms don't work.
Solution: Add custom CSS for extended durations:
body[data-aos-duration='4000'] [data-aos],
[data-aos][data-aos][data-aos-duration='4000'] {
transition-duration: 4000ms;
}<div data-aos="fade-in" data-aos-duration="4000">
Long animation
</div>Built-in Animations
Fade Animations
fade-in- 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 fadefade-up-left- Diagonal fadefade-down-right- Diagonal fadefade-down-left- Diagonal fade
Slide Animations
slide-up- Slide from bottomslide-down- Slide from topslide-left- Slide from rightslide-right- Slide from left
Zoom Animations
zoom-in- Zoom inzoom-in-up- Zoom in from bottomzoom-in-down- Zoom in from topzoom-in-left- Zoom in from rightzoom-in-right- Zoom in from leftzoom-out- Zoom outzoom-out-up- Zoom out to topzoom-out-down- Zoom out to bottomzoom-out-left- Zoom out to leftzoom-out-right- Zoom out to right
Flip Animations
flip-up- Flip from bottomflip-down- Flip from topflip-left- Flip from rightflip-right- Flip from left
Custom Animations
Create custom animations with CSS:
[data-aos="custom-slide-bounce"] {
opacity: 0;
transform: translateY(100px);
transition-property: transform, opacity;
}
[data-aos="custom-slide-bounce"].aos-animate {
opacity: 1;
transform: translateY(0);
animation: bounce 0.5s;
}
@keyframes bounce {
0%, 20%, 50%, 80%, 100% {
transform: translateY(0);
}
40% {
transform: translateY(-10px);
}
60% {
transform: translateY(-5px);
}
}<div data-aos="custom-slide-bounce">
Custom animation
</div>Comparison with Alternatives
AOS vs GSAP ScrollTrigger
| Feature | AOS | GSAP ScrollTrigger |
|---|---|---|
| Complexity | Simple, data-attribute based | Advanced, JavaScript API |
| Use Case | Simple reveals | Complex timelines |
| File Size | ~13KB | ~27KB (GSAP) + ScrollTrigger |
| Performance | CSS-driven | JavaScript-driven |
| Learning Curve | Minutes | Hours |
| Customization | Limited | Extensive |
| Best For | Marketing pages | Interactive experiences |
Use AOS when:
- Simple fade/slide/zoom effects
- Quick implementation needed
- Minimal JavaScript preferred
- Basic scroll reveals sufficient
Use GSAP ScrollTrigger when:
- Complex animation sequences
- Precise scroll-synced animations
- Timeline orchestration needed
- Advanced easing/physics required
Resources
Official Documentation
- AOS: https://michalsnik.github.io/aos/
- GitHub: https://github.com/michalsnik/aos
Key Scripts
scripts/aos_generator.py- Generate AOS HTML boilerplatescripts/config_builder.py- Build AOS configuration
References
references/aos_api.md- Complete AOS API referencereferences/animation_catalog.md- All built-in animations with demosreferences/integration_patterns.md- Framework integration guides
Starter Assets
assets/starter_aos/- Complete AOS starter templateassets/examples/- Production-ready patterns
Related Skills
- gsap-scrolltrigger: For complex scroll-driven animations
- motion-framer: For React-specific animations with physics
- locomotive-scroll: For smooth scrolling with parallax
- animated-component-libraries: For pre-built animated React components
AOS Examples and Integration Patterns
Production-ready code examples for AOS (Animate On Scroll) integration across different frameworks and use cases.
Table of Contents
- Quick Start Templates
- React Integration
- Next.js Integration
- Vue.js Integration
- Common Patterns
- Performance Examples
- Accessibility Patterns
Quick Start Templates
Minimal CDN Setup
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AOS Minimal Example</title>
<link rel="stylesheet" href="https://unpkg.com/aos@next/dist/aos.css" />
</head>
<body>
<h1 data-aos="fade-down">Hello World</h1>
<p data-aos="fade-up" data-aos-delay="200">
This content fades in with a delay.
</p>
<script src="https://unpkg.com/aos@next/dist/aos.js"></script>
<script>
AOS.init({ duration: 800, once: true });
</script>
</body>
</html>NPM Setup (ES6)
npm install aos@next// main.js
import AOS from 'aos';
import 'aos/dist/aos.css';
AOS.init({
duration: 800,
once: true,
offset: 100
});<!-- index.html -->
<div data-aos="fade-up">Content here</div>React Integration
Basic React Setup
// App.jsx
import { useEffect } from 'react';
import AOS from 'aos';
import 'aos/dist/aos.css';
function App() {
useEffect(() => {
AOS.init({
duration: 800,
once: true,
offset: 100,
easing: 'ease-out-cubic'
});
}, []);
return (
<div>
<h1 data-aos="fade-down">Welcome</h1>
<p data-aos="fade-up" data-aos-delay="200">
Your content here
</p>
</div>
);
}
export default App;React with React Router
// App.jsx
import { useEffect } from 'react';
import { useLocation, Routes, Route } from 'react-router-dom';
import AOS from 'aos';
import 'aos/dist/aos.css';
import Home from './pages/Home';
import About from './pages/About';
function App() {
const location = useLocation();
// Initialize AOS on mount
useEffect(() => {
AOS.init({
duration: 800,
once: true,
offset: 100
});
}, []);
// Refresh AOS on route change
useEffect(() => {
AOS.refresh();
}, [location.pathname]);
return (
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
</Routes>
);
}
export default App;React Wrapper Component
// components/AnimatedSection.jsx
import React from 'react';
const AnimatedSection = ({
children,
animation = 'fade-up',
delay = 0,
duration = 800,
offset = 100,
once = true,
className = '',
...props
}) => {
return (
<div
data-aos={animation}
data-aos-delay={delay}
data-aos-duration={duration}
data-aos-offset={offset}
data-aos-once={once}
className={className}
{...props}
>
{children}
</div>
);
};
export default AnimatedSection;Usage:
// pages/Home.jsx
import AnimatedSection from '../components/AnimatedSection';
function Home() {
return (
<main>
<AnimatedSection animation="fade-down">
<h1>Hero Title</h1>
</AnimatedSection>
<AnimatedSection animation="fade-up" delay={200}>
<p>Hero subtext</p>
</AnimatedSection>
<AnimatedSection animation="zoom-in" delay={400}>
<button>Get Started</button>
</AnimatedSection>
</main>
);
}React with Dynamic Content
// components/DynamicList.jsx
import { useState, useEffect } from 'react';
import AOS from 'aos';
function DynamicList() {
const [items, setItems] = useState([]);
useEffect(() => {
AOS.init({ duration: 600 });
}, []);
const addItem = () => {
const newItem = {
id: Date.now(),
text: `Item ${items.length + 1}`
};
setItems([...items, newItem]);
// Refresh AOS after adding to DOM
setTimeout(() => AOS.refresh(), 50);
};
const removeItem = (id) => {
setItems(items.filter(item => item.id !== id));
setTimeout(() => AOS.refresh(), 50);
};
return (
<div>
<button onClick={addItem}>Add Item</button>
<div className="list">
{items.map((item, index) => (
<div
key={item.id}
data-aos="fade-in"
data-aos-delay={index * 50}
>
{item.text}
<button onClick={() => removeItem(item.id)}>Remove</button>
</div>
))}
</div>
</div>
);
}
export default DynamicList;Next.js Integration
Next.js App Router (_app.js)
// pages/_app.js
import { useEffect } from 'react';
import AOS from 'aos';
import 'aos/dist/aos.css';
import '../styles/globals.css';
function MyApp({ Component, pageProps }) {
useEffect(() => {
AOS.init({
duration: 800,
once: true,
offset: 100,
easing: 'ease-out-cubic'
});
}, []);
return <Component {...pageProps} />;
}
export default MyApp;Next.js Page Example
// pages/index.js
export default function Home() {
return (
<main>
<section className="hero">
<h1 data-aos="fade-down">Next.js + AOS</h1>
<p data-aos="fade-up" data-aos-delay="200">
Server-side rendered content with scroll animations
</p>
</section>
<section className="features">
{features.map((feature, index) => (
<div
key={feature.id}
data-aos="fade-up"
data-aos-delay={index * 100}
className="feature-card"
>
<h3>{feature.title}</h3>
<p>{feature.description}</p>
</div>
))}
</section>
</main>
);
}
const features = [
{ id: 1, title: 'Fast', description: 'Lightning fast performance' },
{ id: 2, title: 'Secure', description: 'Enterprise-grade security' },
{ id: 3, title: 'Scalable', description: 'Grows with your needs' }
];Next.js with TypeScript
// pages/_app.tsx
import { useEffect } from 'react';
import type { AppProps } from 'next/app';
import AOS from 'aos';
import 'aos/dist/aos.css';
function MyApp({ Component, pageProps }: AppProps) {
useEffect(() => {
AOS.init({
duration: 800,
once: true
});
}, []);
return <Component {...pageProps} />;
}
export default MyApp;// components/AnimatedCard.tsx
interface AnimatedCardProps {
title: string;
description: string;
delay?: number;
}
const AnimatedCard = ({ title, description, delay = 0 }: AnimatedCardProps) => {
return (
<div
data-aos="fade-up"
data-aos-delay={delay}
className="card"
>
<h3>{title}</h3>
<p>{description}</p>
</div>
);
};
export default AnimatedCard;Vue.js Integration
Vue 3 Composition API
<!-- App.vue -->
<template>
<div>
<h1 data-aos="fade-down">Vue 3 + AOS</h1>
<div
v-for="(item, index) in items"
:key="item.id"
data-aos="fade-up"
:data-aos-delay="index * 100"
>
{{ item.text }}
</div>
</div>
</template>
<script setup>
import { onMounted, ref } from 'vue';
import AOS from 'aos';
import 'aos/dist/aos.css';
const items = ref([
{ id: 1, text: 'Item 1' },
{ id: 2, text: 'Item 2' },
{ id: 3, text: 'Item 3' }
]);
onMounted(() => {
AOS.init({
duration: 800,
once: true
});
});
</script>Vue 3 with Dynamic Updates
<!-- DynamicList.vue -->
<template>
<div>
<button @click="addItem">Add Item</button>
<div
v-for="(item, index) in items"
:key="item.id"
data-aos="fade-in"
:data-aos-delay="index * 50"
class="list-item"
>
{{ item.text }}
</div>
</div>
</template>
<script setup>
import { ref, nextTick, onMounted } from 'vue';
import AOS from 'aos';
import 'aos/dist/aos.css';
const items = ref([]);
onMounted(() => {
AOS.init({ duration: 600 });
});
const addItem = async () => {
items.value.push({
id: Date.now(),
text: `Item ${items.value.length + 1}`
});
// Wait for DOM update, then refresh AOS
await nextTick();
AOS.refresh();
};
</script>Vue 2 Options API
<!-- App.vue -->
<template>
<div>
<h1 data-aos="fade-down">Vue 2 + AOS</h1>
<p data-aos="fade-up">Content here</p>
</div>
</template>
<script>
import AOS from 'aos';
import 'aos/dist/aos.css';
export default {
name: 'App',
mounted() {
AOS.init({
duration: 800,
once: true
});
},
updated() {
// Refresh when component updates
this.$nextTick(() => {
AOS.refresh();
});
}
};
</script>Common Patterns
Landing Page Pattern
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AOS Landing Page</title>
<link rel="stylesheet" href="https://unpkg.com/aos@next/dist/aos.css" />
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; }
/* Hero */
.hero {
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
text-align: center;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
padding: 2rem;
}
.hero h1 { font-size: 3rem; margin-bottom: 1rem; }
.hero p { font-size: 1.25rem; margin-bottom: 2rem; }
.hero button {
padding: 1rem 2.5rem;
font-size: 1.1rem;
background: white;
color: #667eea;
border: none;
border-radius: 50px;
cursor: pointer;
}
/* Features */
.features {
padding: 5rem 2rem;
max-width: 1200px;
margin: 0 auto;
}
.features h2 {
text-align: center;
font-size: 2.5rem;
margin-bottom: 3rem;
}
.feature-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 2rem;
}
.feature-card {
background: white;
padding: 2rem;
border-radius: 12px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
text-align: center;
}
.feature-icon {
font-size: 3rem;
margin-bottom: 1rem;
}
</style>
</head>
<body>
<!-- Hero Section -->
<section class="hero">
<div>
<h1 data-aos="fade-down" data-aos-duration="800">
Build Something Amazing
</h1>
<p data-aos="fade-up" data-aos-delay="200" data-aos-duration="600">
The most powerful platform for creating extraordinary experiences
</p>
<button data-aos="zoom-in" data-aos-delay="400" data-aos-duration="500">
Get Started
</button>
</div>
</section>
<!-- Features Section -->
<section class="features">
<h2 data-aos="fade-down">Why Choose Us</h2>
<div class="feature-grid">
<div class="feature-card" data-aos="fade-up" data-aos-delay="0">
<div class="feature-icon">🚀</div>
<h3>Lightning Fast</h3>
<p>Optimized for speed and performance</p>
</div>
<div class="feature-card" data-aos="fade-up" data-aos-delay="100">
<div class="feature-icon">🎨</div>
<h3>Beautiful UI</h3>
<p>Stunning designs that users love</p>
</div>
<div class="feature-card" data-aos="fade-up" data-aos-delay="200">
<div class="feature-icon">🔒</div>
<h3>Secure</h3>
<p>Enterprise-grade security built-in</p>
</div>
</div>
</section>
<script src="https://unpkg.com/aos@next/dist/aos.js"></script>
<script>
AOS.init({
duration: 800,
once: true,
offset: 100
});
</script>
</body>
</html>Staggered Grid Pattern
// React example
function ProductGrid({ products }) {
useEffect(() => {
AOS.init({ duration: 600, once: true });
}, []);
return (
<div className="product-grid">
{products.map((product, index) => (
<div
key={product.id}
data-aos="zoom-in-up"
data-aos-delay={index * 50}
className="product-card"
>
<img src={product.image} alt={product.name} />
<h3>{product.name}</h3>
<p>{product.price}</p>
</div>
))}
</div>
);
}Alternating Content Pattern
<!-- Alternating image-text sections -->
<div class="content-sections">
<!-- Section 1: Image on right -->
<section class="content-row">
<div class="text-col" data-aos="slide-right" data-aos-duration="800">
<h2>Feature One</h2>
<p>Description of the feature...</p>
</div>
<div class="image-col" data-aos="fade-left" data-aos-delay="200">
<img src="feature1.jpg" alt="Feature 1">
</div>
</section>
<!-- Section 2: Image on left -->
<section class="content-row reverse">
<div class="image-col" data-aos="fade-right">
<img src="feature2.jpg" alt="Feature 2">
</div>
<div class="text-col" data-aos="slide-left" data-aos-duration="800" data-aos-delay="200">
<h2>Feature Two</h2>
<p>Description of the feature...</p>
</div>
</section>
</div>Performance Examples
Optimized Configuration
// Best performance configuration
AOS.init({
// Animation settings
duration: 400, // Shorter = smoother
easing: 'ease', // Simple easing
// Behavior
once: true, // Animate only once (better performance)
mirror: false, // Don't animate out
// Device settings
disable: function() {
// Disable on mobile or reduced motion preference
return window.innerWidth < 768 ||
window.matchMedia('(prefers-reduced-motion: reduce)').matches;
},
// Performance tuning
throttleDelay: 120, // Increase for slower devices
debounceDelay: 80,
disableMutationObserver: true // For fully static content
});Selective Animation
// Don't animate everything - be selective
function BlogPost({ post }) {
return (
<article>
{/* Animate hero elements */}
<h1 data-aos="fade-down">{post.title}</h1>
<p className="meta" data-aos="fade-up" data-aos-delay="100">
{post.author} • {post.date}
</p>
{/* Don't animate body text - better for readability */}
<div className="content">
{post.content}
</div>
{/* Animate CTA */}
<button data-aos="fade-up" className="cta">
Share This Post
</button>
</article>
);
}Accessibility Patterns
Reduced Motion Support
// Respect user's motion preferences
AOS.init({
disable: function() {
return window.matchMedia('(prefers-reduced-motion: reduce)').matches;
}
});Conditional Animation
// React: Disable animations based on user preference
import { useEffect, useState } from 'react';
import AOS from 'aos';
import 'aos/dist/aos.css';
function App() {
const [prefersReducedMotion, setPrefersReducedMotion] = useState(false);
useEffect(() => {
const mediaQuery = window.matchMedia('(prefers-reduced-motion: reduce)');
setPrefersReducedMotion(mediaQuery.matches);
const handleChange = () => setPrefersReducedMotion(mediaQuery.matches);
mediaQuery.addEventListener('change', handleChange);
return () => mediaQuery.removeEventListener('change', handleChange);
}, []);
useEffect(() => {
if (!prefersReducedMotion) {
AOS.init({ duration: 800, once: true });
}
}, [prefersReducedMotion]);
return (
<div>
<h1 data-aos={prefersReducedMotion ? undefined : "fade-down"}>
Accessible Heading
</h1>
</div>
);
}ARIA-friendly Animations
<!-- Use aria-live for important content -->
<div
data-aos="fade-up"
aria-live="polite"
aria-atomic="true"
>
<h2>Important Update</h2>
<p>This content will be announced to screen readers</p>
</div>
<!-- Mark decorative animations -->
<div
data-aos="zoom-in"
aria-hidden="true"
role="presentation"
>
Decorative element
</div>Best Practices Summary
Do's
✅ Initialize AOS once on app mount ✅ Use AOS.refresh() after dynamic content changes ✅ Prefer simpler animations (fade, slide) over complex (flip) ✅ Use once: true for better performance ✅ Disable on mobile if not needed ✅ Respect prefers-reduced-motion preference ✅ Be selective - don't animate everything ✅ Use consistent animation types per page (2-3 max)
Don'ts
❌ Don't initialize AOS multiple times ❌ Don't forget to call AOS.refresh() after adding elements ❌ Don't animate too many elements at once ❌ Don't use very long durations (>1500ms) ❌ Don't ignore accessibility ❌ Don't animate critical content (nav, forms, body text) ❌ Don't mix too many animation types
Troubleshooting Checklist
- [ ] AOS initialized? (
AOS.init()called) - [ ] CSS imported? (
import 'aos/dist/aos.css') - [ ] Valid
data-aosattribute? - [ ] Called
AOS.refresh()after dynamic changes? - [ ] Check browser console for errors
- [ ] Try simplified config (duration, once, offset only)
- [ ] Verify element is in viewport when scrolling
- [ ] Check for CSS conflicts (
opacity,transform)
Additional Resources
- Scripts: Use
scripts/aos_generator.pyto generate HTML templates - Scripts: Use
scripts/config_builder.pyto build custom configurations - References: See
references/aos_api.mdfor complete API documentation - References: See
references/animation_catalog.mdfor all 28 built-in animations - Official Docs: https://michalsnik.github.io/aos/
AOS Animation Catalog
Complete catalog of all 50+ built-in animations available in AOS (Animate On Scroll).
Table of Contents
- Fade Animations
- Slide Animations
- Zoom Animations
- Flip Animations
- Animation Combinations
- Custom Animations
Fade Animations
Fade animations gradually change opacity. These are the simplest and most performant animations.
Basic Fade
fade-in
Simple fade in from transparent to opaque.
<div data-aos="fade-in">Fades in</div>Use cases: Simple reveals, subtle content appearance
Directional Fades
fade-up
Fades in while moving upward from below.
<div data-aos="fade-up">Fades up from bottom</div>Use cases: Content blocks, cards, text sections, CTA buttons
fade-down
Fades in while moving downward from above.
<div data-aos="fade-down">Fades down from top</div>Use cases: Headers, hero titles, navigation menus
fade-left
Fades in while moving left (coming from the right).
<div data-aos="fade-left">Fades left from right</div>Use cases: Text blocks, images on right side of layout
fade-right
Fades in while moving right (coming from the left).
<div data-aos="fade-right">Fades right from left</div>Use cases: Text blocks, images on left side of layout
Diagonal Fades
fade-up-right
Fades in while moving diagonally up and to the right.
<div data-aos="fade-up-right">Fades up-right diagonally</div>Use cases: Grid items, cards in top-left position
fade-up-left
Fades in while moving diagonally up and to the left.
<div data-aos="fade-up-left">Fades up-left diagonally</div>Use cases: Grid items, cards in top-right position
fade-down-right
Fades in while moving diagonally down and to the right.
<div data-aos="fade-down-right">Fades down-right diagonally</div>Use cases: Grid items, cards in bottom-left position
fade-down-left
Fades in while moving diagonally down and to the left.
<div data-aos="fade-down-left">Fades down-left diagonally</div>Use cases: Grid items, cards in bottom-right position
Slide Animations
Slide animations move elements without changing opacity. More dramatic than fades.
slide-up
Slides up from below (no fade).
<div data-aos="slide-up">Slides up</div>Use cases: Modal overlays, bottom sheets, notifications
slide-down
Slides down from above (no fade).
<div data-aos="slide-down">Slides down</div>Use cases: Dropdown menus, alerts, top banners
slide-left
Slides left from the right (no fade).
<div data-aos="slide-left">Slides left</div>Use cases: Side panels, drawer menus, image carousels
slide-right
Slides right from the left (no fade).
<div data-aos="slide-right">Slides right</div>Use cases: Side panels, drawer menus, timeline items
Zoom Animations
Zoom animations scale elements from small to normal size (or vice versa).
Basic Zoom
zoom-in
Zooms in from smaller to normal size, centered.
<div data-aos="zoom-in">Zooms in</div>Use cases: Featured images, product photos, logos, icons
zoom-out
Zooms out from larger to normal size, centered.
<div data-aos="zoom-out">Zooms out</div>Use cases: Background images, hero sections, splash screens
Directional Zoom In
zoom-in-up
Zooms in while moving upward.
<div data-aos="zoom-in-up">Zooms in from bottom</div>Use cases: Gallery images, product cards, testimonials
zoom-in-down
Zooms in while moving downward.
<div data-aos="zoom-in-down">Zooms in from top</div>Use cases: Headers, hero content, call-to-action sections
zoom-in-left
Zooms in while moving left (from right).
<div data-aos="zoom-in-left">Zooms in from right</div>Use cases: Content blocks, feature highlights (right side)
zoom-in-right
Zooms in while moving right (from left).
<div data-aos="zoom-in-right">Zooms in from left</div>Use cases: Content blocks, feature highlights (left side)
Directional Zoom Out
zoom-out-up
Zooms out while moving upward.
<div data-aos="zoom-out-up">Zooms out moving up</div>Use cases: Attention-grabbing elements, special announcements
zoom-out-down
Zooms out while moving downward.
<div data-aos="zoom-out-down">Zooms out moving down</div>Use cases: Hero overlays, introductory content
zoom-out-left
Zooms out while moving left.
<div data-aos="zoom-out-left">Zooms out moving left</div>Use cases: Dynamic content transitions
zoom-out-right
Zooms out while moving right.
<div data-aos="zoom-out-right">Zooms out moving right</div>Use cases: Dynamic content transitions
Flip Animations
Flip animations create 3D rotation effects. These are more complex and should be used sparingly.
flip-up
Flips up (rotates around X-axis).
<div data-aos="flip-up">Flips up</div>Use cases: Cards, product reveals, special features
Note: More CPU-intensive than other animations
flip-down
Flips down (rotates around X-axis).
<div data-aos="flip-down">Flips down</div>Use cases: Cards, dropdown reveals
Note: More CPU-intensive than other animations
flip-left
Flips left (rotates around Y-axis).
<div data-aos="flip-left">Flips left</div>Use cases: Card flips, panel transitions
Note: More CPU-intensive than other animations
flip-right
Flips right (rotates around Y-axis).
<div data-aos="flip-right">Flips right</div>Use cases: Card flips, panel transitions
Note: More CPU-intensive than other animations
Animation Combinations
Staggered Animations
Create sequential reveals by using delays:
<div class="feature-grid">
<div data-aos="fade-up" data-aos-delay="0">Item 1</div>
<div data-aos="fade-up" data-aos-delay="100">Item 2</div>
<div data-aos="fade-up" data-aos-delay="200">Item 3</div>
<div data-aos="fade-up" data-aos-delay="300">Item 4</div>
</div>Recommended delay increment: 50-150ms between items
Mixed Animations
Combine different animation types for visual interest:
<!-- Hero section -->
<h1 data-aos="fade-down">Heading</h1>
<p data-aos="fade-up" data-aos-delay="200">Subtext</p>
<button data-aos="zoom-in" data-aos-delay="400">CTA</button>Alternating Patterns
Create rhythm with alternating directions:
<div class="content-section">
<div class="item" data-aos="fade-right">From left</div>
<div class="item" data-aos="fade-left">From right</div>
<div class="item" data-aos="fade-right">From left</div>
<div class="item" data-aos="fade-left">From right</div>
</div>Custom Animations
Create custom animations using CSS:
Example: Custom Bounce
/* Define animation */
@keyframes custom-bounce {
0%, 20%, 50%, 80%, 100% {
transform: translateY(0);
}
40% {
transform: translateY(-30px);
}
60% {
transform: translateY(-15px);
}
}
/* Apply to AOS element */
[data-aos="custom-bounce"] {
opacity: 0;
transform: translateY(100px);
transition-property: transform, opacity;
}
[data-aos="custom-bounce"].aos-animate {
opacity: 1;
transform: translateY(0);
animation: custom-bounce 1s ease-out;
}<div data-aos="custom-bounce">Bounces in!</div>Example: Custom Rotate
[data-aos="rotate-in"] {
opacity: 0;
transform: rotate(-180deg) scale(0.5);
transition-property: transform, opacity;
}
[data-aos="rotate-in"].aos-animate {
opacity: 1;
transform: rotate(0) scale(1);
}<div data-aos="rotate-in" data-aos-duration="1000">Rotates in!</div>Example: Custom Slide Bounce
[data-aos="slide-bounce"] {
opacity: 0;
transform: translateX(-100px);
transition-property: transform, opacity;
}
[data-aos="slide-bounce"].aos-animate {
opacity: 1;
transform: translateX(0);
animation: bounce-effect 0.6s;
}
@keyframes bounce-effect {
0% { transform: translateX(-100px); }
60% { transform: translateX(10px); }
80% { transform: translateX(-5px); }
100% { transform: translateX(0); }
}<div data-aos="slide-bounce">Slides with bounce!</div>Animation Performance Guide
Performance Ranking (Best to Worst)
1. Fade animations (opacity only)
- Best performance, GPU-accelerated
- Use for most content
2. Slide and Zoom animations (transform only)
- Good performance, GPU-accelerated
- Use for featured content
3. Flip animations (3D transforms)
- Lower performance, more CPU-intensive
- Use sparingly for special elements
Optimization Tips
1. Prefer Simpler Animations
<!-- Better performance -->
<div data-aos="fade-up">Content</div>
<!-- Lower performance -->
<div data-aos="flip-left">Content</div>2. Limit Animation Count
<!-- Good: Selective animation -->
<div class="grid">
<div data-aos="fade-up">Animated</div>
<div>Static</div>
<div>Static</div>
<div data-aos="fade-up">Animated</div>
</div>
<!-- Avoid: Everything animated -->
<div class="grid">
<div data-aos="fade-up">Item 1</div>
<div data-aos="fade-up">Item 2</div>
<div data-aos="fade-up">Item 3</div>
<!-- ...50 more animated items -->
</div>3. Use Shorter Durations
<!-- Fast, smooth -->
<div data-aos="fade-up" data-aos-duration="400">Content</div>
<!-- Potentially janky on slower devices -->
<div data-aos="flip-left" data-aos-duration="1500">Content</div>4. Disable on Mobile (Optional)
AOS.init({
disable: 'mobile' // or window.innerWidth < 768
});Animation Selection Guide
By Content Type
| Content Type | Recommended Animation | Alternative |
|---|---|---|
| Hero Heading | fade-down | zoom-in-down |
| Hero Subtext | fade-up | slide-up |
| CTA Button | zoom-in | fade-up |
| Feature Cards | fade-up (staggered) | zoom-in-up |
| Image Gallery | zoom-in-up | fade-in |
| Testimonials | zoom-in | fade-in |
| Statistics | zoom-in | fade-up |
| Timeline Items | slide-right / slide-left | fade-right / fade-left |
| Modal Overlay | zoom-in | fade-in |
| Notifications | slide-down | fade-down |
| Product Cards | zoom-in-up | fade-up |
| Text Blocks | fade-right / fade-left | slide-right / slide-left |
| Icons | zoom-in | fade-in |
| Navigation | fade-down | slide-down |
By User Experience Goal
| Goal | Animation | Example |
|---|---|---|
| Subtle | fade-in, fade-up | About text, descriptions |
| Attention-grabbing | zoom-in, zoom-out | CTA buttons, special offers |
| Directional flow | slide-*, fade-* with direction | Reading flow, timelines |
| Playful | flip-*, diagonal fades | Portfolio items, creative sections |
| Professional | fade-up, fade-in | Corporate sites, documentation |
Quick Reference
Fade Animations (9)
fade-infade-up,fade-down,fade-left,fade-rightfade-up-right,fade-up-left,fade-down-right,fade-down-left
Slide Animations (4)
slide-up,slide-down,slide-left,slide-right
Zoom Animations (11)
zoom-in,zoom-outzoom-in-up,zoom-in-down,zoom-in-left,zoom-in-rightzoom-out-up,zoom-out-down,zoom-out-left,zoom-out-right
Flip Animations (4)
flip-up,flip-down,flip-left,flip-right
Total: 28 built-in animations
Best Practices
1. Consistency: Stick to 2-3 animation types per page 2. Hierarchy: Use more dramatic animations (zoom, flip) for important content 3. Direction: Match animation direction to layout flow 4. Timing: Use delays to create sequences (100-200ms between items) 5. Performance: Prefer fade/slide over flip animations 6. Mobile: Consider disabling or simplifying animations on mobile 7. Accessibility: Respect prefers-reduced-motion user preference
// Respect reduced motion preference
AOS.init({
disable: function() {
return window.matchMedia('(prefers-reduced-motion: reduce)').matches;
}
});AOS API Reference
Complete reference for AOS (Animate On Scroll) configuration, methods, and data attributes.
Table of Contents
- Initialization
- Global Configuration Options
- Data Attributes
- JavaScript Methods
- Events
- Easing Functions
- Anchor Placement Values
- Disable Options
Initialization
Basic Initialization
import AOS from 'aos';
import 'aos/dist/aos.css';
AOS.init();With Configuration
AOS.init({
// Global settings
duration: 800,
easing: 'ease-in-out',
once: true,
offset: 120
});Global Configuration Options
All options can be set globally via AOS.init() or overridden per-element using data attributes.
Animation Settings
duration
- Type:
number - Default:
400 - Range:
0-3000 - Description: Animation duration in milliseconds
AOS.init({ duration: 800 });<div data-aos="fade-up" data-aos-duration="1000">Content</div>delay
- Type:
number - Default:
0 - Range:
0-3000 - Description: Delay before animation starts (ms)
AOS.init({ delay: 100 });<div data-aos="fade-up" data-aos-delay="200">Content</div>easing
- Type:
string - Default:
"ease" - Description: CSS easing function for animations
- See: Easing Functions for all available values
AOS.init({ easing: 'ease-in-out' });<div data-aos="fade-up" data-aos-easing="ease-out-cubic">Content</div>Trigger Settings
offset
- Type:
number - Default:
120 - Description: Offset (in pixels) from the original trigger point
AOS.init({ offset: 200 });<div data-aos="fade-up" data-aos-offset="100">Content</div>anchorPlacement
- Type:
string - Default:
"top-bottom" - Description: Defines which position of the element regarding the viewport should trigger the animation
- See: Anchor Placement Values for all options
AOS.init({ anchorPlacement: 'center-center' });<div data-aos="fade-up" data-aos-anchor-placement="top-center">Content</div>anchor
- Type:
string | null - Default:
null - Description: CSS selector of element whose scroll position will be used to trigger animation
<div id="trigger-element">Scroll past this...</div>
<div data-aos="fade-up" data-aos-anchor="#trigger-element">Animates when trigger scrolls</div>Behavior Settings
once
- Type:
boolean - Default:
false - Description: Whether animation should happen only once - while scrolling down
AOS.init({ once: true });<div data-aos="fade-up" data-aos-once="true">Content</div>mirror
- Type:
boolean - Default:
false - Description: Whether elements should animate out while scrolling past them
AOS.init({ mirror: true });<div data-aos="fade-up" data-aos-mirror="true">Content</div>Device Settings
disable
- Type:
boolean | string | function - Default:
false - Description: Condition when AOS should be disabled
- See: Disable Options for details
// Disable on mobile
AOS.init({ disable: 'mobile' });
// Disable with function
AOS.init({
disable: function() {
return window.innerWidth < 768;
}
});Performance Settings
startEvent
- Type:
string - Default:
"DOMContentLoaded" - Values:
"DOMContentLoaded","load" - Description: Name of the event dispatched on the document, that AOS should initialize on
AOS.init({ startEvent: 'load' });throttleDelay
- Type:
number - Default:
99 - Description: The delay on throttle used while scrolling (in ms)
AOS.init({ throttleDelay: 120 });debounceDelay
- Type:
number - Default:
50 - Description: The delay on debounce used while resizing window (in ms)
AOS.init({ debounceDelay: 80 });disableMutationObserver
- Type:
boolean - Default:
false - Description: Disables automatic mutations' detections (advanced)
AOS.init({ disableMutationObserver: true });Data Attributes
All configuration options can be set per-element using data attributes:
data-aos
Required. Specifies the animation type.
<div data-aos="fade-up">Content</div>See Animation Catalog for all available animations.
data-aos-duration
Animation duration (overrides global duration)
<div data-aos="fade-up" data-aos-duration="1000">Content</div>data-aos-delay
Animation delay (overrides global delay)
<div data-aos="fade-up" data-aos-delay="500">Content</div>data-aos-easing
Animation easing (overrides global easing)
<div data-aos="fade-up" data-aos-easing="ease-in-cubic">Content</div>data-aos-offset
Offset from trigger point (overrides global offset)
<div data-aos="fade-up" data-aos-offset="200">Content</div>data-aos-anchor
Element whose offset will be used to trigger animation
<div data-aos="fade-up" data-aos-anchor="#trigger">Content</div>data-aos-anchor-placement
Anchor placement (overrides global anchorPlacement)
<div data-aos="fade-up" data-aos-anchor-placement="top-center">Content</div>data-aos-once
Whether to animate only once (overrides global once)
<div data-aos="fade-up" data-aos-once="true">Content</div>data-aos-mirror
Whether to animate out (overrides global mirror)
<div data-aos="fade-up" data-aos-mirror="true">Content</div>data-aos-id
Optional ID for specific element (used with anchors)
<div data-aos="fade-up" data-aos-id="my-element">Content</div>JavaScript Methods
AOS.init(options)
Initialize AOS with optional configuration.
AOS.init({
duration: 800,
once: true
});Parameters:
options(Object): Configuration object
Returns: void
AOS.refresh()
Recalculate all offsets and positions of elements. Should be called after dynamic content changes.
// After adding new elements
const newElement = document.createElement('div');
newElement.setAttribute('data-aos', 'fade-in');
container.appendChild(newElement);
AOS.refresh(); // Recalculate positionsReturns: void
AOS.refreshHard()
Reinitialize array with AOS elements and trigger refresh. More comprehensive than refresh().
// After major DOM changes
AOS.refreshHard();Returns: void
Events
AOS dispatches custom events on animated elements:
aos:in
Fired when element enters the viewport and animation starts.
document.addEventListener('aos:in', ({ detail }) => {
console.log('Animated element:', detail);
});aos:out
Fired when element leaves the viewport (when mirror: true).
document.addEventListener('aos:out', ({ detail }) => {
console.log('Animation reversed:', detail);
});Event Details
Event detail object contains:
- Element reference
- Animation name
- Configuration
document.addEventListener('aos:in', ({ detail }) => {
console.log(detail); // HTMLElement with AOS attributes
});Easing Functions
Available easing values for easing option:
Standard Easing
lineareaseease-inease-outease-in-out
Back Easing
ease-in-backease-out-backease-in-out-back
Sine Easing
ease-in-sineease-out-sineease-in-out-sine
Quad Easing
ease-in-quadease-out-quadease-in-out-quad
Cubic Easing
ease-in-cubicease-out-cubicease-in-out-cubic
Quart Easing
ease-in-quartease-out-quartease-in-out-quart
Usage Example
AOS.init({ easing: 'ease-out-cubic' });<div data-aos="fade-up" data-aos-easing="ease-in-out-sine">Content</div>Anchor Placement Values
Defines which position of element and viewport triggers animation.
Format: {element-position}-{viewport-position}
Element Positions
top- Top edge of elementcenter- Center of elementbottom- Bottom edge of element
Viewport Positions
top- Top edge of viewportcenter- Center of viewportbottom- Bottom edge of viewport
All Combinations
| Value | Description |
|---|---|
top-bottom | Element's top edge hits viewport's bottom edge |
top-center | Element's top edge hits viewport's center |
top-top | Element's top edge hits viewport's top edge |
center-bottom | Element's center hits viewport's bottom edge |
center-center | Element's center hits viewport's center |
center-top | Element's center hits viewport's top edge |
bottom-bottom | Element's bottom edge hits viewport's bottom edge |
bottom-center | Element's bottom edge hits viewport's center |
bottom-top | Element's bottom edge hits viewport's top edge |
Visual Examples
top-bottom (default):
┌─────────────┐
│ Viewport │
│ │
│ │
│ ┌──┼──┐ ← Element top hits viewport bottom
└──────────┼──┘ │
│ El │
└─────┘
center-center:
┌─────────────┐
│ Viewport │
│ ┌──────┼────┐ ← Element center hits viewport center
│ │ Elem │ │
│ └──────┼────┘
└─────────────┘
bottom-top:
┌─────┐
│ El │
┌──────────┼──┐ │ ← Element bottom hits viewport top
│ └──┼──┘
│ Viewport │
│ │
└─────────────┘Usage
<!-- Trigger early (when bottom of element reaches top of viewport) -->
<div data-aos="fade-up" data-aos-anchor-placement="bottom-top">
Content
</div>
<!-- Trigger when centered -->
<div data-aos="fade-up" data-aos-anchor-placement="center-center">
Content
</div>Disable Options
The disable option controls when AOS is disabled.
Boolean
AOS.init({ disable: false }); // Always enabled
AOS.init({ disable: true }); // Always disabledString Values
"mobile"
Disables on mobile devices (phones and tablets).
AOS.init({ disable: 'mobile' });Matches: window.innerWidth < 768 || navigator.userAgent.match(/Mobile|Tablet/)
"phone"
Disables only on phones.
AOS.init({ disable: 'phone' });Matches: window.innerWidth < 480
"tablet"
Disables only on tablets.
AOS.init({ disable: 'tablet' });Matches: window.innerWidth < 1024 && window.innerWidth >= 768
Function
Custom function for fine-grained control.
AOS.init({
disable: function() {
// Disable on small screens
return window.innerWidth < 768;
}
});AOS.init({
disable: function() {
// Disable in IE
return /MSIE|Trident/.test(navigator.userAgent);
}
});AOS.init({
disable: function() {
// Disable based on user preference
return window.matchMedia('(prefers-reduced-motion: reduce)').matches;
}
});Complete Example
import AOS from 'aos';
import 'aos/dist/aos.css';
// Initialize with full configuration
AOS.init({
// Animation settings
duration: 800,
delay: 0,
easing: 'ease-out-cubic',
// Trigger settings
offset: 120,
anchorPlacement: 'top-bottom',
// Behavior
once: true,
mirror: false,
// Device settings
disable: 'mobile',
// Performance
startEvent: 'DOMContentLoaded',
throttleDelay: 99,
debounceDelay: 50,
disableMutationObserver: false
});
// Listen to events
document.addEventListener('aos:in', ({ detail }) => {
console.log('Element animated in:', detail);
});
// Refresh after dynamic changes
function addNewElement() {
const el = document.createElement('div');
el.setAttribute('data-aos', 'fade-up');
el.textContent = 'New content';
document.body.appendChild(el);
// Refresh AOS to detect new element
AOS.refresh();
}Browser Support
AOS works in all modern browsers:
- Chrome (latest)
- Firefox (latest)
- Safari (latest)
- Edge (latest)
- iOS Safari (latest)
- Chrome for Android (latest)
Note: IE11 support requires polyfills for:
Array.prototype.forEachElement.prototype.classListObject.assign
Performance Considerations
Best Practices
1. Use `once: true` for better performance
AOS.init({ once: true });2. Increase throttle/debounce delays on slower devices
AOS.init({
throttleDelay: 120,
debounceDelay: 80
});3. Disable on mobile if not needed
AOS.init({ disable: 'mobile' });4. Use simpler animations
- Prefer
fade-*overflip-* - Avoid excessive animation count
5. Call `refresh()` sparingly
- Only after actual DOM changes
- Debounce if calling frequently
Accessibility
Respect user preferences for reduced motion:
AOS.init({
disable: function() {
return window.matchMedia('(prefers-reduced-motion: reduce)').matches;
}
});Troubleshooting
Animations not triggering
1. Verify AOS is initialized: AOS.init() 2. Check CSS is imported: import 'aos/dist/aos.css' 3. Ensure data-aos attribute is set 4. Call AOS.refresh() after dynamic content
Elements flash before animating
Add to global CSS:
[data-aos] {
pointer-events: none;
}
[data-aos].aos-animate {
pointer-events: auto;
}Animations not working in React
Initialize in useEffect:
useEffect(() => {
AOS.init();
}, []);Refresh on route changes:
const location = useLocation();
useEffect(() => {
AOS.refresh();
}, [location]);#!/usr/bin/env python3
"""
AOS HTML Generator
Generates HTML boilerplate with AOS scroll animations.
Creates ready-to-use HTML files with common AOS patterns.
Usage:
./aos_generator.py # Interactive mode
./aos_generator.py --template landing # Use template
./aos_generator.py --template hero --output hero.html
"""
import sys
import argparse
import os
# HTML Templates
TEMPLATES = {
"hero": {
"name": "Hero Section",
"description": "Animated hero section with heading, subtext, and CTA",
"html": """<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AOS Hero Section</title>
<link rel="stylesheet" href="https://unpkg.com/aos@next/dist/aos.css" />
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
color: white;
}
.hero {
text-align: center;
padding: 2rem;
max-width: 800px;
}
h1 {
font-size: 3.5rem;
font-weight: 800;
margin-bottom: 1.5rem;
line-height: 1.2;
}
p {
font-size: 1.25rem;
margin-bottom: 2rem;
opacity: 0.9;
}
.cta-button {
display: inline-block;
padding: 1rem 2.5rem;
font-size: 1.1rem;
font-weight: 600;
color: #667eea;
background: white;
border: none;
border-radius: 50px;
cursor: pointer;
text-decoration: none;
transition: transform 0.2s;
}
.cta-button:hover {
transform: scale(1.05);
}
</style>
</head>
<body>
<section class="hero">
<h1 data-aos="fade-down" data-aos-duration="800">
Welcome to the Future
</h1>
<p data-aos="fade-up" data-aos-delay="200" data-aos-duration="600">
Transform your ideas into reality with cutting-edge technology
</p>
<a href="#" class="cta-button" data-aos="zoom-in" data-aos-delay="400" data-aos-duration="500">
Get Started
</a>
</section>
<script src="https://unpkg.com/aos@next/dist/aos.js"></script>
<script>
AOS.init({
duration: 800,
once: true
});
</script>
</body>
</html>"""
},
"features": {
"name": "Feature Cards",
"description": "Grid of animated feature cards",
"html": """<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AOS Feature Cards</title>
<link rel="stylesheet" href="https://unpkg.com/aos@next/dist/aos.css" />
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
background: #f7fafc;
padding: 4rem 2rem;
}
.container {
max-width: 1200px;
margin: 0 auto;
}
h1 {
text-align: center;
font-size: 2.5rem;
margin-bottom: 3rem;
color: #2d3748;
}
.features-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 2rem;
}
.feature-card {
background: white;
padding: 2rem;
border-radius: 12px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
transition: transform 0.3s, box-shadow 0.3s;
}
.feature-card:hover {
transform: translateY(-5px);
box-shadow: 0 12px 24px rgba(0, 0, 0, 0.15);
}
.feature-icon {
width: 60px;
height: 60px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border-radius: 12px;
display: flex;
align-items: center;
justify-content: center;
font-size: 2rem;
margin-bottom: 1rem;
}
h3 {
font-size: 1.5rem;
margin-bottom: 0.75rem;
color: #2d3748;
}
p {
color: #718096;
line-height: 1.6;
}
</style>
</head>
<body>
<div class="container">
<h1 data-aos="fade-down">Our Features</h1>
<div class="features-grid">
<div class="feature-card" data-aos="fade-up" data-aos-duration="600" data-aos-delay="0">
<div class="feature-icon">🚀</div>
<h3>Fast Performance</h3>
<p>Lightning-fast load times and smooth interactions for the best user experience.</p>
</div>
<div class="feature-card" data-aos="fade-up" data-aos-duration="600" data-aos-delay="100">
<div class="feature-icon">🎨</div>
<h3>Beautiful Design</h3>
<p>Carefully crafted interfaces that are both functional and aesthetically pleasing.</p>
</div>
<div class="feature-card" data-aos="fade-up" data-aos-duration="600" data-aos-delay="200">
<div class="feature-icon">🔒</div>
<h3>Secure</h3>
<p>Enterprise-grade security to keep your data safe and protected.</p>
</div>
<div class="feature-card" data-aos="fade-up" data-aos-duration="600" data-aos-delay="300">
<div class="feature-icon">📱</div>
<h3>Responsive</h3>
<p>Works perfectly on all devices from mobile phones to desktop computers.</p>
</div>
<div class="feature-card" data-aos="fade-up" data-aos-duration="600" data-aos-delay="400">
<div class="feature-icon">⚡</div>
<h3>Easy to Use</h3>
<p>Intuitive interface that requires no training to get started.</p>
</div>
<div class="feature-card" data-aos="fade-up" data-aos-duration="600" data-aos-delay="500">
<div class="feature-icon">🌟</div>
<h3>Quality Support</h3>
<p>24/7 customer support ready to help you whenever you need assistance.</p>
</div>
</div>
</div>
<script src="https://unpkg.com/aos@next/dist/aos.js"></script>
<script>
AOS.init({
duration: 800,
once: true
});
</script>
</body>
</html>"""
},
"landing": {
"name": "Landing Page",
"description": "Complete landing page with multiple sections",
"html": """<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AOS Landing Page</title>
<link rel="stylesheet" href="https://unpkg.com/aos@next/dist/aos.css" />
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
color: #2d3748;
line-height: 1.6;
}
section {
padding: 5rem 2rem;
}
.container {
max-width: 1200px;
margin: 0 auto;
}
/* Hero */
.hero {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
text-align: center;
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
}
.hero h1 {
font-size: 3.5rem;
margin-bottom: 1.5rem;
}
.hero p {
font-size: 1.25rem;
margin-bottom: 2rem;
opacity: 0.9;
}
.cta-button {
display: inline-block;
padding: 1rem 2.5rem;
font-size: 1.1rem;
font-weight: 600;
color: #667eea;
background: white;
border-radius: 50px;
text-decoration: none;
transition: transform 0.2s;
}
.cta-button:hover {
transform: scale(1.05);
}
/* Features */
.features {
background: #f7fafc;
}
.features h2 {
text-align: center;
font-size: 2.5rem;
margin-bottom: 3rem;
}
.features-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 2rem;
}
.feature {
text-align: center;
padding: 2rem;
}
.feature-icon {
font-size: 3rem;
margin-bottom: 1rem;
}
/* Testimonials */
.testimonials {
background: white;
}
.testimonials h2 {
text-align: center;
font-size: 2.5rem;
margin-bottom: 3rem;
}
.testimonial {
background: #f7fafc;
padding: 2rem;
border-radius: 12px;
margin-bottom: 2rem;
}
.testimonial p {
font-size: 1.1rem;
margin-bottom: 1rem;
font-style: italic;
}
.testimonial cite {
font-weight: 600;
color: #667eea;
}
/* CTA */
.cta-section {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
text-align: center;
}
.cta-section h2 {
font-size: 2.5rem;
margin-bottom: 1.5rem;
}
</style>
</head>
<body>
<!-- Hero Section -->
<section class="hero">
<div class="container">
<h1 data-aos="fade-down" data-aos-duration="800">
Build Something Amazing
</h1>
<p data-aos="fade-up" data-aos-delay="200" data-aos-duration="600">
The most powerful platform for creating extraordinary experiences
</p>
<a href="#" class="cta-button" data-aos="zoom-in" data-aos-delay="400">
Start Free Trial
</a>
</div>
</section>
<!-- Features Section -->
<section class="features">
<div class="container">
<h2 data-aos="fade-down">Why Choose Us</h2>
<div class="features-grid">
<div class="feature" data-aos="fade-up" data-aos-delay="0">
<div class="feature-icon">🚀</div>
<h3>Lightning Fast</h3>
<p>Optimized for speed and performance</p>
</div>
<div class="feature" data-aos="fade-up" data-aos-delay="100">
<div class="feature-icon">🎨</div>
<h3>Beautiful UI</h3>
<p>Stunning designs that users love</p>
</div>
<div class="feature" data-aos="fade-up" data-aos-delay="200">
<div class="feature-icon">🔒</div>
<h3>Secure</h3>
<p>Enterprise-grade security built-in</p>
</div>
</div>
</div>
</section>
<!-- Testimonials Section -->
<section class="testimonials">
<div class="container">
<h2 data-aos="fade-down">What Our Customers Say</h2>
<div class="testimonial" data-aos="zoom-in" data-aos-duration="500">
<p>"This product completely transformed how we work. Incredible!"</p>
<cite>— Sarah Johnson, CEO at TechCorp</cite>
</div>
<div class="testimonial" data-aos="zoom-in" data-aos-duration="500" data-aos-delay="100">
<p>"Best investment we've made this year. Highly recommended!"</p>
<cite>— Michael Chen, Founder at StartupXYZ</cite>
</div>
<div class="testimonial" data-aos="zoom-in" data-aos-duration="500" data-aos-delay="200">
<p>"The support team is amazing and the product is even better."</p>
<cite>— Emma Davis, Designer at CreativeStudio</cite>
</div>
</div>
</section>
<!-- CTA Section -->
<section class="cta-section">
<div class="container">
<h2 data-aos="fade-down">Ready to Get Started?</h2>
<p data-aos="fade-up" data-aos-delay="200">
Join thousands of happy customers today
</p>
<a href="#" class="cta-button" data-aos="zoom-in" data-aos-delay="400">
Start Free Trial
</a>
</div>
</section>
<script src="https://unpkg.com/aos@next/dist/aos.js"></script>
<script>
AOS.init({
duration: 800,
once: true,
offset: 100
});
</script>
</body>
</html>"""
},
"gallery": {
"name": "Image Gallery",
"description": "Animated image gallery with zoom effects",
"html": """<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AOS Image Gallery</title>
<link rel="stylesheet" href="https://unpkg.com/aos@next/dist/aos.css" />
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
background: #f7fafc;
padding: 4rem 2rem;
}
.container {
max-width: 1200px;
margin: 0 auto;
}
h1 {
text-align: center;
font-size: 2.5rem;
margin-bottom: 3rem;
color: #2d3748;
}
.gallery {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 2rem;
}
.gallery-item {
position: relative;
overflow: hidden;
border-radius: 12px;
aspect-ratio: 4/3;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
cursor: pointer;
transition: transform 0.3s;
}
.gallery-item:hover {
transform: scale(1.02);
}
.gallery-item::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.3);
opacity: 0;
transition: opacity 0.3s;
}
.gallery-item:hover::before {
opacity: 1;
}
.gallery-caption {
position: absolute;
bottom: 0;
left: 0;
right: 0;
padding: 1.5rem;
color: white;
background: linear-gradient(to top, rgba(0,0,0,0.7), transparent);
transform: translateY(100%);
transition: transform 0.3s;
}
.gallery-item:hover .gallery-caption {
transform: translateY(0);
}
.gallery-caption h3 {
font-size: 1.25rem;
margin-bottom: 0.5rem;
}
</style>
</head>
<body>
<div class="container">
<h1 data-aos="fade-down">Our Portfolio</h1>
<div class="gallery">
<div class="gallery-item" data-aos="zoom-in-up" data-aos-duration="800" data-aos-delay="0">
<div class="gallery-caption">
<h3>Project Alpha</h3>
<p>Modern web application</p>
</div>
</div>
<div class="gallery-item" data-aos="zoom-in-up" data-aos-duration="800" data-aos-delay="100">
<div class="gallery-caption">
<h3>Project Beta</h3>
<p>E-commerce platform</p>
</div>
</div>
<div class="gallery-item" data-aos="zoom-in-up" data-aos-duration="800" data-aos-delay="200">
<div class="gallery-caption">
<h3>Project Gamma</h3>
<p>Mobile app design</p>
</div>
</div>
<div class="gallery-item" data-aos="zoom-in-up" data-aos-duration="800" data-aos-delay="300">
<div class="gallery-caption">
<h3>Project Delta</h3>
<p>Brand identity</p>
</div>
</div>
<div class="gallery-item" data-aos="zoom-in-up" data-aos-duration="800" data-aos-delay="400">
<div class="gallery-caption">
<h3>Project Epsilon</h3>
<p>Marketing campaign</p>
</div>
</div>
<div class="gallery-item" data-aos="zoom-in-up" data-aos-duration="800" data-aos-delay="500">
<div class="gallery-caption">
<h3>Project Zeta</h3>
<p>Product photography</p>
</div>
</div>
</div>
</div>
<script src="https://unpkg.com/aos@next/dist/aos.js"></script>
<script>
AOS.init({
duration: 800,
once: true
});
</script>
</body>
</html>"""
},
"timeline": {
"name": "Timeline",
"description": "Vertical timeline with alternating content",
"html": """<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AOS Timeline</title>
<link rel="stylesheet" href="https://unpkg.com/aos@next/dist/aos.css" />
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
background: #f7fafc;
padding: 4rem 2rem;
}
.container {
max-width: 900px;
margin: 0 auto;
}
h1 {
text-align: center;
font-size: 2.5rem;
margin-bottom: 4rem;
color: #2d3748;
}
.timeline {
position: relative;
padding-left: 3rem;
}
.timeline::before {
content: '';
position: absolute;
left: 0;
top: 0;
bottom: 0;
width: 2px;
background: #667eea;
}
.timeline-item {
position: relative;
margin-bottom: 3rem;
}
.timeline-item::before {
content: '';
position: absolute;
left: -3.5rem;
top: 0;
width: 1rem;
height: 1rem;
background: #667eea;
border-radius: 50%;
border: 3px solid #f7fafc;
}
.timeline-content {
background: white;
padding: 2rem;
border-radius: 12px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
.timeline-date {
color: #667eea;
font-weight: 600;
margin-bottom: 0.5rem;
}
.timeline-content h3 {
font-size: 1.5rem;
margin-bottom: 0.75rem;
color: #2d3748;
}
.timeline-content p {
color: #718096;
line-height: 1.6;
}
</style>
</head>
<body>
<div class="container">
<h1 data-aos="fade-down">Our Journey</h1>
<div class="timeline">
<div class="timeline-item" data-aos="slide-right" data-aos-duration="800">
<div class="timeline-content">
<div class="timeline-date">January 2020</div>
<h3>Company Founded</h3>
<p>Started with a vision to transform the industry and make a difference.</p>
</div>
</div>
<div class="timeline-item" data-aos="slide-right" data-aos-duration="800" data-aos-delay="100">
<div class="timeline-content">
<div class="timeline-date">June 2020</div>
<h3>First Product Launch</h3>
<p>Released our flagship product to market with overwhelming positive response.</p>
</div>
</div>
<div class="timeline-item" data-aos="slide-right" data-aos-duration="800" data-aos-delay="200">
<div class="timeline-content">
<div class="timeline-date">December 2020</div>
<h3>Reached 10,000 Users</h3>
<p>Hit a major milestone with rapid user growth and engagement.</p>
</div>
</div>
<div class="timeline-item" data-aos="slide-right" data-aos-duration="800" data-aos-delay="300">
<div class="timeline-content">
<div class="timeline-date">March 2021</div>
<h3>Series A Funding</h3>
<p>Secured significant investment to scale operations and expand the team.</p>
</div>
</div>
<div class="timeline-item" data-aos="slide-right" data-aos-duration="800" data-aos-delay="400">
<div class="timeline-content">
<div class="timeline-date">Present</div>
<h3>Global Expansion</h3>
<p>Continuing to grow and serve customers worldwide with innovative solutions.</p>
</div>
</div>
</div>
</div>
<script src="https://unpkg.com/aos@next/dist/aos.js"></script>
<script>
AOS.init({
duration: 800,
once: true
});
</script>
</body>
</html>"""
}
}
def list_templates():
"""List all available templates."""
print("\nAvailable Templates:")
print("=" * 60)
for template_id, template in TEMPLATES.items():
print(f"\n{template_id}")
print(f" Name: {template['name']}")
print(f" Description: {template['description']}")
print()
def generate_html(template_name, output_path=None):
"""Generate HTML from template."""
if template_name not in TEMPLATES:
print(f"Error: Template '{template_name}' not found")
print("\nAvailable templates:")
for tid in TEMPLATES.keys():
print(f" - {tid}")
return False
template = TEMPLATES[template_name]
html_content = template["html"]
if output_path:
try:
with open(output_path, 'w', encoding='utf-8') as f:
f.write(html_content)
print(f"✓ Generated {template['name']}: {output_path}")
return True
except Exception as e:
print(f"Error writing file: {e}")
return False
else:
# Output to stdout
print(html_content)
return True
def interactive_mode():
"""Run interactive HTML generator."""
print("\nAOS HTML Generator - Interactive Mode")
print("=" * 60)
list_templates()
print("Enter template name:")
template_name = input("> ").strip().lower()
if template_name not in TEMPLATES:
print(f"Error: Template '{template_name}' not found")
return
print("\nEnter output filename (or press Enter to print to console):")
output_path = input("> ").strip()
if not output_path:
output_path = None
generate_html(template_name, output_path)
def main():
parser = argparse.ArgumentParser(
description="Generate HTML boilerplate with AOS animations"
)
parser.add_argument(
"--template",
choices=list(TEMPLATES.keys()),
help="Template to use"
)
parser.add_argument(
"--output",
help="Output file path (default: print to console)"
)
parser.add_argument(
"--list",
action="store_true",
help="List available templates"
)
args = parser.parse_args()
if args.list:
list_templates()
elif args.template:
generate_html(args.template, args.output)
else:
interactive_mode()
if __name__ == "__main__":
main()
#!/usr/bin/env python3
"""
AOS Config Builder
Generates AOS initialization configurations with customizable options.
Outputs JavaScript code for AOS.init() with selected settings.
Usage:
./config_builder.py # Interactive mode
./config_builder.py --preset marketing # Use preset
./config_builder.py --duration 1000 --once true # Custom config
"""
import sys
import argparse
import json
# Configuration presets
PRESETS = {
"marketing": {
"name": "Marketing Page",
"description": "Optimized for marketing/landing pages with once-only animations",
"config": {
"duration": 800,
"delay": 0,
"offset": 120,
"easing": "ease-out",
"once": True,
"mirror": False,
"anchorPlacement": "top-bottom",
"disable": "mobile"
}
},
"interactive": {
"name": "Interactive Experience",
"description": "Repeating animations for interactive scrolling experiences",
"config": {
"duration": 600,
"delay": 0,
"offset": 80,
"easing": "ease-in-out",
"once": False,
"mirror": True,
"anchorPlacement": "center-center",
"disable": False
}
},
"blog": {
"name": "Blog/Content Site",
"description": "Subtle animations for content-heavy sites",
"config": {
"duration": 500,
"delay": 0,
"offset": 100,
"easing": "ease",
"once": True,
"mirror": False,
"anchorPlacement": "top-bottom",
"disable": False
}
},
"performance": {
"name": "Performance Optimized",
"description": "Minimal animations for best performance",
"config": {
"duration": 400,
"delay": 0,
"offset": 50,
"easing": "linear",
"once": True,
"mirror": False,
"anchorPlacement": "top-bottom",
"disable": "mobile",
"disableMutationObserver": True,
"throttleDelay": 120,
"debounceDelay": 80
}
},
"showcase": {
"name": "Portfolio/Showcase",
"description": "Dramatic animations for portfolios and showcases",
"config": {
"duration": 1200,
"delay": 100,
"offset": 150,
"easing": "ease-out-cubic",
"once": False,
"mirror": True,
"anchorPlacement": "center-center",
"disable": False
}
}
}
# Available configuration options
CONFIG_OPTIONS = {
"duration": {
"type": "number",
"default": 800,
"range": [0, 3000],
"description": "Animation duration in milliseconds"
},
"delay": {
"type": "number",
"default": 0,
"range": [0, 3000],
"description": "Delay before animation starts (ms)"
},
"offset": {
"type": "number",
"default": 120,
"description": "Offset (in px) from original trigger point"
},
"easing": {
"type": "enum",
"default": "ease",
"values": [
"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"
],
"description": "Easing function for animations"
},
"once": {
"type": "boolean",
"default": False,
"description": "Whether animation should happen only once"
},
"mirror": {
"type": "boolean",
"default": False,
"description": "Whether elements should animate out while scrolling past them"
},
"anchorPlacement": {
"type": "enum",
"default": "top-bottom",
"values": [
"top-bottom", "top-center", "top-top",
"center-bottom", "center-center", "center-top",
"bottom-bottom", "bottom-center", "bottom-top"
],
"description": "Anchor placement - which position triggers animation"
},
"disable": {
"type": "mixed",
"default": False,
"values": [False, "mobile", "phone", "tablet"],
"description": "Disable AOS on specific devices"
},
"startEvent": {
"type": "enum",
"default": "DOMContentLoaded",
"values": ["DOMContentLoaded", "load"],
"description": "Event on which AOS should be initialized"
},
"disableMutationObserver": {
"type": "boolean",
"default": False,
"description": "Disable mutation observer (for static content)"
},
"throttleDelay": {
"type": "number",
"default": 99,
"description": "Delay on throttle used while scrolling (ms)"
},
"debounceDelay": {
"type": "number",
"default": 50,
"description": "Delay on debounce used while resizing window (ms)"
}
}
def format_value(key, value):
"""Format configuration value for JavaScript output."""
if isinstance(value, bool):
return "true" if value else "false"
elif isinstance(value, str):
return f"'{value}'"
elif value is False:
return "false"
else:
return str(value)
def generate_js_config(config, format_type="modern"):
"""Generate JavaScript AOS initialization code."""
lines = []
if format_type == "modern":
lines.append("import AOS from 'aos';")
lines.append("import 'aos/dist/aos.css';")
lines.append("")
elif format_type == "cdn":
lines.append("<!-- Add to <head> -->")
lines.append('<link rel="stylesheet" href="https://unpkg.com/aos@next/dist/aos.css" />')
lines.append("")
lines.append("<!-- Add before </body> -->")
lines.append('<script src="https://unpkg.com/aos@next/dist/aos.js"></script>')
lines.append("<script>")
lines.append("AOS.init({")
# Sort config keys for consistent output
sorted_config = sorted(config.items())
for i, (key, value) in enumerate(sorted_config):
comma = "," if i < len(sorted_config) - 1 else ""
# Add comment for each option
if key in CONFIG_OPTIONS:
lines.append(f" // {CONFIG_OPTIONS[key]['description']}")
lines.append(f" {key}: {format_value(key, value)}{comma}")
lines.append("});")
if format_type == "cdn":
lines.append("</script>")
return "\n".join(lines)
def generate_react_config(config):
"""Generate React AOS initialization code."""
lines = [
"import { useEffect } from 'react';",
"import AOS from 'aos';",
"import 'aos/dist/aos.css';",
"",
"function App() {",
" useEffect(() => {",
" AOS.init({"
]
sorted_config = sorted(config.items())
for i, (key, value) in enumerate(sorted_config):
comma = "," if i < len(sorted_config) - 1 else ""
lines.append(f" {key}: {format_value(key, value)}{comma}")
lines.extend([
" });",
" }, []);",
"",
" return (",
" <div>",
" <h1 data-aos=\"fade-down\">Your Content</h1>",
" </div>",
" );",
"}"
])
return "\n".join(lines)
def list_presets():
"""List all available configuration presets."""
print("\nAvailable Presets:")
print("=" * 60)
for preset_id, preset in PRESETS.items():
print(f"\n{preset_id}")
print(f" Name: {preset['name']}")
print(f" Description: {preset['description']}")
print(f" Config: {json.dumps(preset['config'], indent=2)}")
print()
def interactive_mode():
"""Run interactive configuration builder."""
print("\nAOS Config Builder - Interactive Mode")
print("=" * 60)
# Ask if user wants to start from a preset
print("\nWould you like to start from a preset? (y/n)")
use_preset = input("> ").strip().lower()
config = {}
if use_preset == 'y':
list_presets()
print("Enter preset name (or press Enter for default):")
preset_name = input("> ").strip().lower()
if preset_name in PRESETS:
config = PRESETS[preset_name]["config"].copy()
print(f"\nStarting with '{PRESETS[preset_name]['name']}' preset")
else:
print("\nNo preset selected, building from scratch")
print("\nConfigure AOS options (press Enter to use default/current):")
print("=" * 60)
for option_name, option_info in CONFIG_OPTIONS.items():
current_value = config.get(option_name, option_info["default"])
print(f"\n{option_name}")
print(f" Description: {option_info['description']}")
print(f" Type: {option_info['type']}")
print(f" Current: {current_value}")
if option_info["type"] == "enum" or option_info["type"] == "mixed":
print(f" Options: {', '.join(str(v) for v in option_info['values'])}")
elif "range" in option_info:
print(f" Range: {option_info['range'][0]} - {option_info['range'][1]}")
value = input(" Value: ").strip()
if value:
# Convert value based on type
if option_info["type"] == "number":
try:
config[option_name] = float(value) if '.' in value else int(value)
except ValueError:
print(" Invalid number, using current value")
config[option_name] = current_value
elif option_info["type"] == "boolean":
config[option_name] = value.lower() in ["true", "yes", "1"]
elif option_info["type"] == "mixed":
if value.lower() in ["false", "no", "0"]:
config[option_name] = False
else:
config[option_name] = value
else:
config[option_name] = value
else:
config[option_name] = current_value
# Select output format
print("\n\nSelect output format:")
print(" 1. Modern ES6 (import)")
print(" 2. CDN (script tags)")
print(" 3. React")
format_choice = input("\nFormat (1-3): ").strip()
print("\n" + "=" * 60)
print("Generated Configuration:")
print("=" * 60 + "\n")
if format_choice == "2":
print(generate_js_config(config, "cdn"))
elif format_choice == "3":
print(generate_react_config(config))
else:
print(generate_js_config(config, "modern"))
print()
def main():
parser = argparse.ArgumentParser(
description="Generate AOS initialization configurations"
)
parser.add_argument(
"--preset",
choices=list(PRESETS.keys()),
help="Use a configuration preset"
)
parser.add_argument(
"--format",
choices=["modern", "cdn", "react"],
default="modern",
help="Output format (default: modern)"
)
parser.add_argument(
"--list-presets",
action="store_true",
help="List available presets"
)
# Individual config options
for option_name, option_info in CONFIG_OPTIONS.items():
arg_name = f"--{option_name.replace('_', '-')}"
if option_info["type"] == "boolean":
parser.add_argument(arg_name, type=lambda x: x.lower() == 'true')
elif option_info["type"] == "number":
parser.add_argument(arg_name, type=int)
else:
parser.add_argument(arg_name, type=str)
args = parser.parse_args()
if args.list_presets:
list_presets()
elif args.preset or any(getattr(args, opt.replace('-', '_'), None) is not None
for opt in CONFIG_OPTIONS.keys()):
# CLI mode with preset or custom config
if args.preset:
config = PRESETS[args.preset]["config"].copy()
else:
config = {}
# Override with CLI arguments
for option_name in CONFIG_OPTIONS.keys():
arg_value = getattr(args, option_name, None)
if arg_value is not None:
config[option_name] = arg_value
if args.format == "react":
print(generate_react_config(config))
else:
print(generate_js_config(config, args.format))
else:
interactive_mode()
if __name__ == "__main__":
main()
Related skills
How it compares
Choose scroll-reveal-libraries for simple CSS scroll reveals; switch to GSAP ScrollTrigger or Locomotive Scroll when scroll behavior needs orchestration beyond basic fades and slides.
FAQ
What does scroll-reveal-libraries do?
Simple scroll-triggered reveal animations using AOS (Animate On Scroll). Use this skill when building marketing pages, landing pages, or content-heavy sites requiring basic fade/slide effects without complex animation or
When should I use scroll-reveal-libraries?
Simple scroll-triggered reveal animations using AOS (Animate On Scroll). Use this skill when building marketing pages, landing pages, or content-heavy sites requiring basic fade/slide effects without complex animation or
What are common prerequisites?
--- name: scroll-reveal-libraries description: Simple scroll-triggered reveal animations using AOS (Animate On Scroll).
Is Scroll Reveal Libraries safe to install?
skills.sh reports 3 of 3 security scanners passed. Review the Security Audits panel on this page before installing in production.