
MurphyJS is a lightweight JavaScript AOS (animate on scroll) library that triggers reveal animations on HTML elements as they scroll into view.
It uses the Intersection Observer API to detect when elements enter the viewport and then utilizes the Web Animations API to create smooth, performant animations.
Features:
- Simple API: Get started quickly with
data-attributesor use the programmatic API for more control. - Configurable: Fine-tune animations with various
data-attributesfor distance, easing, delay, duration, and Intersection Observer parameters likeroot-marginandthreshold. - Built-in Animations: Comes with common effects like
bottom-to-top,left-to-right, etc. - Event System: Hooks into animation lifecycle events (
murphy:in,murphy:out,murphy:finish, etc.) for advanced interactions. - Native Fallback: Provides basic functionality if Intersection Observer or Web Animations API aren’t supported.
- Group Animations: Control animations for specific sets of elements.
How to use it:
1. Install MurphyJS via npm or yarn:
# Yarn $ yarn add murphyjs # NPM $ npm install murphyjs
2. For quick prototyping, you can also include it via script tag:
<script src="./dist/index.js"></script>
3. Add the data-murphy attribute to the elements you want to animate on scroll. All possible animations:
- bottom-to-top
- top-to-bottom
- left-to-right
- right-to-left
- flip-left
- flip-right
- flip-up
- flip-down
- zoom-in
- zoom-out
- fade
- fade-up
- fade-down
- fade-left
- fade-right
- rotate-left
- rotate-right
- scale-up
- scale-down
- slide-up
- slide-down
- slide-left
- slide-right
- bounce-in
- bounce-out
<div data-murphy="left-to-right"> Left to Right </div> <div data-murphy="right-to-left"> Right to Left </div> <div data-murphy="top-to-bottom"> Top To Bottom </div> <div data-murphy="bottom-to-top"> Bottom to Top </div>
4. You need to set the initial state of your elements to be invisible. MurphyJS will then transition them to visible.
*[data-murphy] {
opacity: 0;
}5. Initialize MurphyJS in your JavaScript:
// If using modules import murphy from "murphyjs"; murphy.play();
// If using script tag <script> window.murphy.play(); </script>
6. Configure animations using the following data attributes:
data-murphy-animation-duration– Duration in milliseconds (default: 300ms)data-murphy-animation-delay– Delay before animation starts (default: 300ms)data-murphy-element-distance– Distance the element moves during animation (default: 30px)data-murphy-ease– Easing function (default: ease, can be cubic-bezier)data-murphy-element-threshold– How much of element must be visible to trigger (0-1)data-murphy-appearance-distance– Distance from viewport edge to triggerdata-murphy-root-margin– Root margin for Intersection Observer
<div data-murphy="right-to-left" data-murphy-animation-duration="500" data-murphy-animation-delay="200" data-murphy-element-distance="50" data-murphy-ease="ease-in-out"> Customized animation </div>
7. You can assign elements to groups and control them collectively:
<div data-murphy="bottom-to-top" data-murphy-group="intro">Section 1</div> <div data-murphy="bottom-to-top" data-murphy-group="intro">Section 2</div> <div data-murphy="left-to-right" data-murphy-group="features">Feature 1</div> <div data-murphy="left-to-right" data-murphy-group="features">Feature 2</div>
// Play only the intro group
murphy.play('intro');
// Reset the features group
murphy.reset('features');8. For more complex animations, you can use the Murphy class:
const murphyInstance = new Murphy();
murphyInstance.animate('.my-custom-element', {
opacity: [0, 1], // from 0 to 1
x: [0, 0],
y: [20, 0], // translate Y from 20px to 0px
duration: 800,
ease: 'ease-out',
delay: 100
});9. API methods.
murphy.play(groupName?: string): Starts observingdata-murphyelements. Optionally, specify a group name.murphy.reset(groupName?: string): Resetsdata-murphyelements to their initial (hidden) state. Optionally, specify a group.murphy.cleanup(): Disconnects all Intersection Observers tied to the default instance. Call this when elements are removed or the page/component unmounts to prevent memory leaks. This is one I always make sure to use in SPAs.
10. Events.
murphy:in: Element enters the viewport.murphy:out: Element leaves the viewport.murphy:finish: Animation completes.murphy:cancel: Animation is cancelled.murphy:reset: Element is reset.murphy:cleanup: Observers are cleaned up.
document.addEventListener('murphy:in', ({ detail }) => {
console.log('Element entered:', detail.element);
// detail also includes intersectionRatio
detail.element.classList.add('is-now-visible');
});
document.addEventListener('murphy:finish', ({ detail }) => {
console.log('Animation finished for:', detail.element);
});Changelog:
v2.5.1 (05/21/2025)
- Added more animations







