
ScrollMoo is a robust JavaScript animation library that enables you to create high-performance, keyframe-based, and scroll-triggered animations on any elements.
The library takes a different approach from traditional CSS @keyframes by organizing animations around individual CSS properties rather than timeline positions.
Each property gets its own set of keyframes, which makes the code more readable and provides better control over complex animations.
Features:
- Property-based keyframe system for better code organization
- Support for CSS transforms, filters, backdrop-filters, and custom properties
- Visual markers for development debugging
- Flexible trigger and indicator positioning
- Built-in easing functions and timing controls
- Performance optimizations including optional 3D rendering
- Callback system for animation lifecycle events
See it in action:
How to use it:
1. Install & download ScrollMoo with NPM.
# NPM $ npm install scrollmoo
2. Import it into your project.
// ES Module import ScrollMoo from "scrollmoo"; // Local import ScrollMoo from "./dist/scrollmoo.esm.min.js"; // Locally // Browser <script src="/path/to/dist/scrollmoo.min.js"></script>
3. Initialize ScrollMoo on the target element and configure your scroll animation(s) as follows:
let SM = ScrollMoo({
".target-element": {
keyframes: {
// config your animation here
}
}
});4. All possible configuration options and callback functions.
keyframes: An object defining the CSS properties to animate. Each key is a camelCased CSS property, and its value is an object mapping animation percentages (0-100) to CSS values.markers: A boolean or object. Iftrue, it displays visual guides for trigger and indicator positions during development. You can pass an object to customize the marker styles.markerId: A string used to add a text label to the markers. This is helpful for identifying which animation’s markers you are looking at when multiple elements are animated.sync: A number in seconds. It defines a smoothing duration for the animation to “catch up” to the current scroll position. A higher value creates more lag. It is ignored ifdurationis set.duration: A number in seconds. It sets a fixed total time for the animation to run from start to end, regardless of scroll speed. This overrides thesyncproperty.ease: A string that specifies an easing function for the animation timing, affecting its acceleration and deceleration. The default isoutQuadfor a smooth finish.triggerStartElement: A string CSS selector. It sets a different element to act as the starting trigger for the animation instead of the animated element itself.triggerEndElement: A string CSS selector. It sets a different element to act as the ending trigger for the animation.triggerStart: A number or string (%orpx). It offsets the start trigger position relative to thetriggerStartElement‘s top edge.triggerEnd: A number or string (%orpx). It offsets the end trigger position relative to thetriggerEndElement‘s bottom edge.indicatorStart: A number or string (%orpx). It defines the position within the viewport (the “playhead”) that thetriggerStartmust cross to begin the animation.indicatorEnd: A number or string (%orpx). It defines the viewport position that thetriggerEndmust cross to end the animation.render3D: A boolean. Iftrue, it composes alltransformproperties into a singlematrix3d()style. Only enable this for actual 3D animations to avoid potential performance issues.onEnter: A callback function that fires when thetriggerStartscrolls up past theindicatorStart.onEnterReverse: A callback function that fires when thetriggerEndscrolls down past theindicatorEnd.onLeave: A callback function that fires when thetriggerEndscrolls up past theindicatorEnd.onLeaveReverse: A callback function that fires when thetriggerStartscrolls down past theindicatorStart.onProgress: A callback that fires continuously as the animation progresses. It receives the animated elements and a progress value (0 to 1) as arguments.onAnimationComplete: A callback that fires when thesyncordurationtime has finished after a scroll event.
let SM = ScrollMoo({
".target-element": {
sync: .35,
duration: false,
ease: "none",
markers: false,
markerId: "",
triggerStartElement: "",
triggerEndElement: "",
triggerStart: 0,
triggerEnd: 0,
indicatorStart: 0,
indicatorEnd: 0,
render3D: false,
keyframes: {},
onEnter: function(elements){},
onEnterReverse: function(elements){},
onLeave: function(elements){},
onLeaveReverse: function(elements){},
onProgress: function(elements, progress){},
onAnimationComplete: function(elements){},
onToggle: function(elements){},
}
});5. API methods.
SM.refresh(): ScrollMoo caches element positions for performance. If you dynamically add elements to the page or change the layout with JavaScript, you’ll need to callrefresh()to force recalculation.SM.destroy(true): This stops all animations and removes event listeners. Passingtruerestores the elements to their original, pre-animation styles.
Supported CSS Properties
Common Properties
width: Animates the width of an element. Accepts standard CSS length units (px,%,vw, etc.).height: Animates the height of an element. Accepts standard CSS length units.color: Animates the text color. Accepts all CSS color data types (red,rgba(...),#fff).backgroundColor: Animates the background color. Accepts all CSS color data types.opacity: Animates the transparency of an element from 0 (transparent) to 1 (opaque).
Transform Properties
These properties must be nested inside a transform object in your keyframes.
perspective: Sets the distance between the user and the Z=0 plane for 3D transforms.translate,translateX,translateY,translateZ,translate3d: Moves an element along the X, Y, or Z axes.scale,scaleX,scaleY,scaleZ,scale3d: Resizes an element. A value of 1 is the original size.rotate,rotateX,rotateY,rotateZ,rotate3d: Rotates an element in 2D or 3D space. Accepts angle units (deg,rad,turn).skew,skewX,skewY: Skews an element along the X or Y axis. Accepts angle units.
Filter Properties
These properties must be nested inside a filter object in your keyframes.
blur: Applies a Gaussian blur. Accepts length units (px,rem).brightness: Adjusts the brightness.0is black,1is original.contrast: Adjusts the contrast.0is gray,1is original.grayscale: Converts the element to shades of gray.0is original,1is fully grayscale.hueRotate: Rotates the colors around the color wheel. Accepts angle units.invert: Inverts the colors.0is original,1is fully inverted.opacity: Adjusts transparency within the filter.0is transparent,1is original.saturate: Adjusts the color saturation.0is desaturated,1is original.sepia: Applies a sepia tone.0is original,1is fully sepia.
Backdrop Filter Properties
These properties must be nested inside a backdropFilter object. They apply effects to the area behind a semi-transparent element. The supported functions are the same as filter: blur, brightness, contrast, grayscale, hueRotate, invert, opacity, saturate, and sepia.
CSS Custom Properties (Variables)
--scrollmoo-*: Allows you to animate any CSS custom property that has a numerical value. You must define a unit (e.g., px, deg, or "" for unitless numbers) within the property’s keyframe object. This enables animation for properties not natively prepared by ScrollMoo, such as border-radius or font-size.
Related Resources:
Changelog:
v1.1.11 (08/16/2025)
- Fixed bugs
v1.1.10 (08/09/2025)
- Fixed bug on backdropFilter rendering
v1.1.9 (08/06/2025)
- Fixed bugs
- Added new callback: onToggle
v1.1.8 (08/03/2025)
- Bugfixed
v1.1.6 (08/01/2025)
- Fixed bugs (there was an issue for the value conversion on rotate3d, translate3d, scale3d)
- Improved performance
v1.1.5 (07/26/2025)
- Bugfixes
v1.1.3 (07/24/2025)
- Bugfixes
v1.1.2 (07/24/2025)
- Fixed keyframe comparison







