
This is a lightweight scroll animation library that implements performance-focused, scroll-triggered animations in your web applications.
It uses the Intersection Observer API to detect when elements enter the viewport, then applies Animate.css animation classes to the target element when scrolling down or up.
Features:
- Automatic element detection: Finds and animates elements based on common CSS classes
- Staggered animations: Sequential timing for multiple elements within containers
- Custom animation presets: Define reusable animation configurations
- Debug mode with performance monitoring: Real-time metrics and detailed logging
- Accessibility compliance: Automatic reduced motion support via media queries
- Flexible API: Both declarative HTML attributes and programmatic JavaScript control
- Event system: Custom events for animation lifecycle management
See it in action:
How to use it:
1. Download the package or install it with NPM.
# NPM $ npm install scroll-animation-framework
2. Load the scroll animation library together with the required Animate.css library in the document.
<!-- Animate.css --> <link rel="stylesheet" href="/path/to/cdn/animate.min.css"> <!-- Scroll Animation Framework --> <script src="/path/to/dist/js/scroll-animation-framework.min.js"></script>
3. Apply scroll-triggered animations to elements using the following data attributes:
data-scroll-animate: Animation name from Animate.css (required)data-scroll-duration: CSS duration value like “1.5s” or “800ms”data-scroll-delay: Delay in milliseconds before animation startsdata-scroll-callback: JavaScript function name to call after animationdata-scroll-container: Marks parent for staggered child animationsdata-scroll-stagger: Milliseconds between each child animation
<!-- Simple animation --> <div data-scroll-animate="fadeInUp">Hello World!</div> <!-- With detailed settings --> <div data-scroll-animate="bounceIn" data-scroll-duration="1.5s" data-scroll-delay="200"> Detailed Animation </div> <!-- With all settings --> <div data-scroll-animate="slideInLeft" data-scroll-duration="2s" data-scroll-delay="500" data-scroll-callback="myCallback"> Fully Controlled Animation </div>
<!-- Multiple animations with container --> <div data-scroll-container data-scroll-animate="fadeInUp" data-scroll-stagger="200"> <div class="item">Element 1</div> <div class="item">Element 2</div> <div class="item">Element 3</div> </div> <!-- With different animations --> <div data-scroll-container data-scroll-animate="bounceIn" data-scroll-duration="1.2s" data-scroll-stagger="150"> <div class="card">Card 1</div> <div class="card">Card 2</div> <div class="card">Card 3</div> </div>
<!-- With callback function -->
<div data-scroll-animate="jackInTheBox"
data-scroll-callback="elementAnimated">
Element with Callback
</div>
<!-- With different threshold -->
<div data-scroll-animate="rotateIn"
data-scroll-threshold="0.8">
Late Triggered Element
</div>
<!-- Combination example -->
<section data-scroll-container data-scroll-animate="fadeInUp" data-scroll-stagger="100">
<h2 data-scroll-animate="slideInDown" data-scroll-delay="0">Title</h2>
<p data-scroll-animate="fadeIn" data-scroll-delay="200">Description</p>
<div class="cards">
<div class="card">Card 1</div>
<div class="card">Card 2</div>
<div class="card">Card 3</div>
</div>
</section>4. You can also use Class-based auto detection:
<div class="card">This gets automatic slide-up animation</div> <div class="hero-title">This gets automatic fade animation</div> <div class="feature-box">This gets automatic slide-left animation</div> <button class="button">This gets automatic bounce animation</button>
5. The library starts scroll animations automatically by default. To disable:
<script> window.SCROLL_ANIMATOR_AUTO_INIT = false; </script>
and then initialize it manually:
const scrollAnimator = new ScrollAnimationFramework ({
// options here
});6. All possible options.
defaultAnimation: Sets the default animation name to use whendata-scroll-animateis not specified on an element.defaultDuration: Defines the default animation duration for all elements.staggerDelay: Specifies the default delay in milliseconds between animations for child elements inside adata-scroll-container.debug: A boolean that, whentrue, enables detailed logging in the console to help with development and troubleshooting.performanceMonitor: A boolean that, whentrue, activates real-time performance monitoring, which can be accessed via the API.threshold: An array of numbers between 0.0 and 1.0 that defines at what percentage of the element’s visibility the animation should trigger. This is passed directly to the Intersection Observer.rootMargin: A string (e.g.,'0px 0px -50px 0px') that adjusts the bounding box for intersection calculations, allowing you to trigger animations before or after an element is strictly in the viewport.onElementAnimated: A callback function that executes after an individual element completes its animation. It receives the element and its configuration as arguments.onAllAnimationsComplete: A callback function that runs once all initially detected animations on the page have completed.classMappings: An object that maps your custom CSS classes to specific Animate.css animation names for automatic detection.presets: An object where you can define reusable animation configurations (e.g., a preset combining a specific animation, duration, and delay).
const scrollAnimator = new ScrollAnimationFramework ({
// Basic settings
threshold: [0, 0.1, 0.25, 0.5, 0.75, 1.0],
rootMargin: "0px 0px -100px 0px",
// Animation settings
defaultAnimation: "fadeInUp",
defaultDuration: "1s",
defaultDelay: 0,
// Stagger settings
staggerDelay: 150,
// Debug settings
debug: false,
performanceMonitor: false,
// Selectors
selectors: {
animated: "[data-scroll-animate]",
container: "[data-scroll-container]",
trigger: "[data-scroll-trigger]",
ignore: "[data-scroll-ignore]",
},
// Animation presets with correct Animate.css classes
presets: {
// Attention Seekers
bounce: { animation: "bounce", duration: "1s" },
flash: { animation: "flash", duration: "1s" },
pulse: { animation: "pulse", duration: "1s" },
rubberBand: { animation: "rubberBand", duration: "1s" },
shakeX: { animation: "shakeX", duration: "1s" },
shakeY: { animation: "shakeY", duration: "1s" },
headShake: { animation: "headShake", duration: "1s" },
swing: { animation: "swing", duration: "1s" },
tada: { animation: "tada", duration: "1s" },
wobble: { animation: "wobble", duration: "1s" },
jello: { animation: "jello", duration: "1s" },
heartBeat: { animation: "heartBeat", duration: "1.3s" },
// Back Entrances
backInDown: { animation: "backInDown", duration: "1s" },
backInLeft: { animation: "backInLeft", duration: "1s" },
backInRight: { animation: "backInRight", duration: "1s" },
backInUp: { animation: "backInUp", duration: "1s" },
// Back Exits
backOutDown: { animation: "backOutDown", duration: "1s" },
backOutLeft: { animation: "backOutLeft", duration: "1s" },
backOutRight: { animation: "backOutRight", duration: "1s" },
backOutUp: { animation: "backOutUp", duration: "1s" },
// Bouncing Entrances
bounceIn: { animation: "bounceIn", duration: "0.75s" },
bounceInDown: { animation: "bounceInDown", duration: "1s" },
bounceInLeft: { animation: "bounceInLeft", duration: "1s" },
bounceInRight: { animation: "bounceInRight", duration: "1s" },
bounceInUp: { animation: "bounceInUp", duration: "1s" },
// Bouncing Exits
bounceOut: { animation: "bounceOut", duration: "0.75s" },
bounceOutDown: { animation: "bounceOutDown", duration: "1s" },
bounceOutLeft: { animation: "bounceOutLeft", duration: "1s" },
bounceOutRight: { animation: "bounceOutRight", duration: "1s" },
bounceOutUp: { animation: "bounceOutUp", duration: "1s" },
// Fading Entrances
fadeIn: { animation: "fadeIn", duration: "1s" },
fadeInDown: { animation: "fadeInDown", duration: "1s" },
fadeInDownBig: { animation: "fadeInDownBig", duration: "1.3s" },
fadeInLeft: { animation: "fadeInLeft", duration: "1s" },
fadeInLeftBig: { animation: "fadeInLeftBig", duration: "1.3s" },
fadeInRight: { animation: "fadeInRight", duration: "1s" },
fadeInRightBig: { animation: "fadeInRightBig", duration: "1.3s" },
fadeInUp: { animation: "fadeInUp", duration: "1s" },
fadeInUpBig: { animation: "fadeInUpBig", duration: "1.3s" },
fadeInTopLeft: { animation: "fadeInTopLeft", duration: "1s" },
fadeInTopRight: { animation: "fadeInTopRight", duration: "1s" },
fadeInBottomLeft: { animation: "fadeInBottomLeft", duration: "1s" },
fadeInBottomRight: { animation: "fadeInBottomRight", duration: "1s" },
// Fading Exits
fadeOut: { animation: "fadeOut", duration: "1s" },
fadeOutDown: { animation: "fadeOutDown", duration: "1s" },
fadeOutDownBig: { animation: "fadeOutDownBig", duration: "1.3s" },
fadeOutLeft: { animation: "fadeOutLeft", duration: "1s" },
fadeOutLeftBig: { animation: "fadeOutLeftBig", duration: "1.3s" },
fadeOutRight: { animation: "fadeOutRight", duration: "1s" },
fadeOutRightBig: { animation: "fadeOutRightBig", duration: "1.3s" },
fadeOutUp: { animation: "fadeOutUp", duration: "1s" },
fadeOutUpBig: { animation: "fadeOutUpBig", duration: "1.3s" },
fadeOutTopLeft: { animation: "fadeOutTopLeft", duration: "1s" },
fadeOutTopRight: { animation: "fadeOutTopRight", duration: "1s" },
fadeOutBottomRight: { animation: "fadeOutBottomRight", duration: "1s" },
fadeOutBottomLeft: { animation: "fadeOutBottomLeft", duration: "1s" },
// Flippers
flip: { animation: "flip", duration: "1s" },
flipInX: { animation: "flipInX", duration: "1s" },
flipInY: { animation: "flipInY", duration: "1s" },
flipOutX: { animation: "flipOutX", duration: "0.75s" },
flipOutY: { animation: "flipOutY", duration: "0.75s" },
// Lightspeed
lightSpeedInRight: { animation: "lightSpeedInRight", duration: "1s" },
lightSpeedInLeft: { animation: "lightSpeedInLeft", duration: "1s" },
lightSpeedOutRight: { animation: "lightSpeedOutRight", duration: "1s" },
lightSpeedOutLeft: { animation: "lightSpeedOutLeft", duration: "1s" },
// Rotating Entrances
rotateIn: { animation: "rotateIn", duration: "1s" },
rotateInDownLeft: { animation: "rotateInDownLeft", duration: "1s" },
rotateInDownRight: { animation: "rotateInDownRight", duration: "1s" },
rotateInUpLeft: { animation: "rotateInUpLeft", duration: "1s" },
rotateInUpRight: { animation: "rotateInUpRight", duration: "1s" },
// Rotating Exits
rotateOut: { animation: "rotateOut", duration: "1s" },
rotateOutDownLeft: { animation: "rotateOutDownLeft", duration: "1s" },
rotateOutDownRight: { animation: "rotateOutDownRight", duration: "1s" },
rotateOutUpLeft: { animation: "rotateOutUpLeft", duration: "1s" },
rotateOutUpRight: { animation: "rotateOutUpRight", duration: "1s" },
// Sliding Entrances
slideInDown: { animation: "slideInDown", duration: "1s" },
slideInLeft: { animation: "slideInLeft", duration: "1s" },
slideInRight: { animation: "slideInRight", duration: "1s" },
slideInUp: { animation: "slideInUp", duration: "1s" },
// Sliding Exits
slideOutDown: { animation: "slideOutDown", duration: "1s" },
slideOutLeft: { animation: "slideOutLeft", duration: "1s" },
slideOutRight: { animation: "slideOutRight", duration: "1s" },
slideOutUp: { animation: "slideOutUp", duration: "1s" },
// Zooming Entrances
zoomIn: { animation: "zoomIn", duration: "1s" },
zoomInDown: { animation: "zoomInDown", duration: "1s" },
zoomInLeft: { animation: "zoomInLeft", duration: "1s" },
zoomInRight: { animation: "zoomInRight", duration: "1s" },
zoomInUp: { animation: "zoomInUp", duration: "1s" },
// Zooming Exits
zoomOut: { animation: "zoomOut", duration: "1s" },
zoomOutDown: { animation: "zoomOutDown", duration: "1.5s" },
zoomOutLeft: { animation: "zoomOutLeft", duration: "1s" },
zoomOutRight: { animation: "zoomOutRight", duration: "1s" },
zoomOutUp: { animation: "zoomOutUp", duration: "1s" },
// Specials
hinge: { animation: "hinge", duration: "2s" },
jackInTheBox: { animation: "jackInTheBox", duration: "1s" },
rollIn: { animation: "rollIn", duration: "1s" },
rollOut: { animation: "rollOut", duration: "1s" },
// Common shortcuts for easier usage
fade: { animation: "fadeIn", duration: "0.8s" },
"slide-up": { animation: "fadeInUp", duration: "0.8s" },
"slide-down": { animation: "fadeInDown", duration: "0.8s" },
"slide-left": { animation: "fadeInLeft", duration: "0.8s" },
"slide-right": { animation: "fadeInRight", duration: "0.8s" },
zoom: { animation: "zoomIn", duration: "0.6s" },
elastic: { animation: "bounceIn", duration: "1.2s" },
attention: { animation: "pulse", duration: "1s" },
jack: { animation: "jackInTheBox", duration: "1s" },
},
// Auto class detection mappings
classMappings: {
card: "slide-up",
"hero-title": "fade",
"stats-item": "bounce",
"feature-box": "slide-left",
testimonial: "slide-right",
"section-title": "slide-down",
button: "bounce",
"demo-card": "zoom",
},
// Callbacks
onElementAnimated: null,
onAllAnimationsComplete: null,
});Or set options globally.
window.SCROLL_ANIMATOR_CONFIG = {
// options here
};7. Available API methods:
addElement(element, config): Add new element to observationremoveElement(element): Stop observing elementtriggerAnimation(selector, config): Force animation on elementsresetAllAnimations(): Reset all elements to pre-animation stateupdateConfig(newConfig): Change framework settingspauseAnimations()/resumeAnimations(): Control animation stategetStats(): Retrieve performance and usage statistics







