You’ve probably encountered websites with various animations happening as you scroll down (On Scroll Animations). I’ll share with you a library called AOS (Animate On Scroll), which allows you to easily add these animations with full CSS control over them.
The concept behind AOS is quite simple: track all the elements and their positions according to the settings you provide, and then add or remove the aos-animate class that triggers the animation for the relevant element.
“Actually, it’s not as simple as it sounds,” notes the developer of the library, but the idea behind it is straightforward, and every aspect of animation is managed through CSS only.
How to Use the AOS Library
To start, you need to include the necessary files for AOS to work. Add the stylesheet file to the <head> of your page:
<link rel="stylesheet" href="https://unpkg.com/aos@2.3.4/dist/aos.css" />Then, add the required script just before the closing </body> tag:
<script src="https://unpkg.com/aos@2.3.4/dist/aos.js"></script>The examples above use aos@2.3.4, which is the latest stable release. You may see references to aos@next online – that points to a 3.0 beta that has been in development for years. Stick with 2.3.4 for production sites.
I won’t explain here how to add these in WordPress, as I’ve covered that extensively in previous posts with lots of examples. You’re welcome to take a look at the post on Adding CSS and JS to WordPress Sites. If you’re struggling, feel free to ask in the comments, and I promise to respond.
To save you time, you can download both relevant files from this link.
Initializing the AOS Library
To initialize the library, use the following code:
AOS.init();
AOS has several options, which I won’t expand upon here. The comments in the code provide excellent explanations.
Adding Animation to HTML Elements
Let’s take a look at an example of how to add animation to any HTML element. Assuming you’ve loaded the library correctly, adding animation to an element is done like this:
<div class="some-item" data-aos="fade">Example Element</div>The result will be something like this (according to the CSS of that element):
Or, for instance, the same example but with a longer animation duration:
<div class="some-item" data-aos="fade" data-aos-duration="2500">Example Element</div>The result:
You probably understood that the attribute
data-aos is responsible for the type of animation. Let’s change the animation for demonstration purposes:<div class="some-item" data-aos="flip-left" data-aos-duration="1500">Example Element</div>And here’s the result:
You can also set a delay for elements using the
data-aos-delay parameter. Here are three buttons with short delays between them:<div class="buttons-aos">
<button class="aos-button" data-aos="fade-up" data-aos-delay="0" data-aos-easing="ease-in-out">Button</button>
<button class="aos-button" data-aos="fade-up" data-aos-delay="500" data-aos-easing="ease-in-out">Button</button>
<button class="aos-button" data-aos="fade-up" data-aos-delay="1000" data-aos-easing="ease-in-out">Button</button>
</div>Here’s how it looks:
Available Animations
AOS ships with a solid set of built-in animations you can use right away. Here are the main groups:
- Fade:
fade,fade-up,fade-down,fade-left,fade-right,fade-up-right,fade-up-left,fade-down-right,fade-down-left - Flip:
flip-up,flip-down,flip-left,flip-right - Slide:
slide-up,slide-down,slide-left,slide-right - Zoom:
zoom-in,zoom-in-up,zoom-in-down,zoom-in-left,zoom-in-right,zoom-out,zoom-out-up,zoom-out-down,zoom-out-left,zoom-out-right
Each animation accepts parameters like data-aos-duration, data-aos-delay, data-aos-easing, and data-aos-offset to fine-tune the behavior.
AOS Configuration Options
When initializing AOS, you can pass a configuration object to control global behavior. Here is a full example with all available options:
AOS.init({
// Global settings:
disable: false, // accepts: 'phone', 'tablet', 'mobile', boolean, expression or function
startEvent: 'DOMContentLoaded', // event that triggers AOS initialization
initClassName: 'aos-init', // class applied after initialization
animatedClassName: 'aos-animate', // class applied on animation
useClassNames: false, // if true, adds data-aos value as classes on scroll
disableMutationObserver: false, // disables automatic mutation detection (advanced)
debounceDelay: 50, // debounce delay on window resize (advanced)
throttleDelay: 99, // throttle delay on scroll (advanced)
// Per-element settings (overridable via data-aos-* attributes):
offset: 120, // offset (in px) from the trigger point
delay: 0, // values from 0 to 3000, step 50ms
duration: 400, // values from 0 to 3000, step 50ms
easing: 'ease', // default easing for animations
once: false, // whether animation runs only once while scrolling down
mirror: false, // whether elements animate out while scrolling past them
anchorPlacement: 'top-bottom', // which position of the element triggers the animation
});
A common setup for production is setting once: true so animations play once and don’t repeat every time the user scrolls back up. This feels less distracting and improves scrolling performance.
Adding Your Own Animation to AOS
If the animations provided by the library aren’t enough and you want to add your own animation to AOS, it’s quite simple since all animations are performed through CSS.
[data-aos="new-animation"] {
opacity: 0;
transition-property: transform, opacity;
}
[data-aos="new-animation"].aos-animate {
opacity: 1;
}
@media screen and (min-width: 768px) {
[data-aos="new-animation"] {
transform: translateX(100px);
}
[data-aos="new-animation"].aos-animate {
transform: translateX(0);
}
}
You can then use this animation like this:
<div data-aos="new-animation"></div>Accessibility Considerations
Scroll animations can be problematic for users who are sensitive to motion. Modern browsers support the prefers-reduced-motion media query, and you should respect it. AOS makes this easy with the disable option:
AOS.init({
disable: window.matchMedia('(prefers-reduced-motion: reduce)').matches
});
This disables all AOS animations when the user has requested reduced motion in their operating system settings.
Native CSS Scroll-Driven Animations
It’s worth mentioning that browsers are rolling out native CSS scroll-driven animations through the animation-timeline property with scroll() and view() functions. This allows you to tie CSS animations to scroll progress without any JavaScript at all.
As of early 2026, Chrome, Edge, and Safari support this feature, but Firefox still has it disabled by default. For broad browser support, AOS remains a reliable choice. Keep an eye on animation-timeline as it matures – it may eventually replace JavaScript-based scroll animation libraries entirely.
FAQs
Common questions about AOS and scroll animations:
aos@next) has been in development but has not reached a stable release.once: true option so animations run only once, and avoid animating dozens of elements on the same page.AOS.init() in the mounted or useEffect hook, and add data-aos attributes to your JSX or template elements. If the DOM changes dynamically, call AOS.refresh() after updates so AOS picks up the new elements.disable option. For example: AOS.init({ disable: window.matchMedia('(prefers-reduced-motion: reduce)').matches }). This turns off all scroll animations when the user has enabled reduced motion in their OS settings.once and mirror in AOS?
once option controls whether the animation plays only on the first scroll-down. When set to true, the element animates in once and stays visible. The mirror option controls whether elements animate out (reverse) when you scroll past them. By default both are false, so animations replay every time the element enters the viewport.[data-aos="your-animation-name"] with the initial state, and another rule for [data-aos="your-animation-name"].aos-animate with the final state. Then use data-aos="your-animation-name" on any element. Since all animations are CSS-based, you have full control over transforms, opacity, and transitions.Summary
AOS is a lightweight, CSS-driven library that makes adding scroll animations straightforward. Set the data-aos attribute on any element, initialize the library, and you’re done. For production, pin to version 2.3.4, set once: true for a cleaner experience, and remember to disable animations for users who prefer reduced motion.
You can find more information about the library’s options, available animations, and all parameters on the AOS GitHub page.

