- 🚀 Lightweight and fast (only 3.7KB)
- 🎨 Simple and intuitive API
- 🌈 Beautiful animations
- 📱 Mobile-friendly
- 🎯 No dependencies
- 🎮 Total control of IntersectionObserver parameters
- 🎁 Some animations implemented by default
- 🏝 Plug and play solution to landing pages and simple projects
- ❎ Native fallback to not supported browsers
- 🛎️ Built-in event system for animation lifecycle (in, out, finish, cancel, reset, cleanup)
- 🔄 Mirror animations for smooth scroll transitions
- 📏 Viewport position control with predefined aliases
- 📱 Mobile optimization with device detection
Using npm:
npm install murphyjsUsing yarn:
yarn add murphyjsUsing CDN:
<scriptsrc="https://unpkg.com/murphyjs@2.5.1/dist/index.js"></script><script>// Call play() after the script is loadedif(typeofwindow!=="undefined"&&window.murphy){window.murphy.play();}</script>For detailed documentation and examples, visit our documentation site.
import{Murphy}from'murphyjs';// Create a new instanceconstmurphy=newMurphy();// Animate elementsmurphy.animate('.box',{opacity: [0,1],y: [20,0],duration: 1000});In your markup, decorate your element with attribute data-murphy:
<divdata-murphy="left-to-right">Any content here</div>The default effect of murphy is bottom-to-top, but you can also use:
top-to-bottomleft-to-rightright-to-left
In your CSS, reset all the tagged elements:
*[data-murphy] {
opacity:0;
}In JavaScript, import and run play when your page is completely loaded:
importmurphyfrom"murphyjs";murphy.play();Or if you're using the script tag:
<scriptsrc="./murphy/index.js"></script><script>murphy.play();</script>You can configure the animation of each decorated element individually using these attributes:
| Attribute | Type | Default | Description |
|---|---|---|---|
| data-murphy | String | 'bottom-to-top' | Animation direction |
| data-murphy-appearance-distance | Int | 50px | Distance from viewport edge to trigger animation |
| data-murphy-element-distance | Int | 30px | Distance the element moves during animation |
| data-murphy-ease | String | 'ease' | Animation easing function (can be a cubic-bezier) |
| data-murphy-animation-delay | Int | 300ms | Delay before animation starts |
| data-murphy-element-threshold | Float | 1.0 | How much of the element needs to be visible to trigger (0-1) |
| data-murphy-animation-duration | Int | 300ms | Duration of the animation |
| data-murphy-root-margin | String | '0px 0px -50px 0px' | Custom root margin for the Intersection Observer. Use this to control when animations trigger based on viewport position. You can use predefined aliases: 'top', 'middle', 'bottom', 'quarter', 'three-quarters' |
| data-murphy-group | String | undefined | Group identifier for controlling animations for specific groups of elements |
| data-murphy-mirror | Boolean | false | Whether to play the animation in reverse when the element leaves the viewport |
| data-murphy-disable-mobile | Boolean | false | Whether to disable animations on mobile devices (screen width <= 768px or mobile user agent) |
Enable mirror animations to create smooth transitions when elements leave the viewport:
<divdata-murphy="bottom-to-top" data-murphy-mirror="true">
This element will animate in when scrolling down and animate out when scrolling up
</div>Control when animations trigger based on the element's position in the viewport using the data-murphy-root-margin attribute. For convenience, we provide several aliases:
<!-- Animate when element reaches middle of viewport --><divdata-murphy="bottom-to-top" data-murphy-root-margin="middle">
This will animate when it reaches the middle of the viewport
</div><!-- Animate when element reaches bottom of viewport --><divdata-murphy="bottom-to-top" data-murphy-root-margin="bottom">
This will animate when it reaches the bottom of the viewport
</div><!-- Animate when element is 25% from bottom of viewport --><divdata-murphy="bottom-to-top" data-murphy-root-margin="quarter">
This will animate when it's 25% from the bottom of the viewport
</div><!-- Animate when element is 75% from bottom of viewport --><divdata-murphy="bottom-to-top" data-murphy-root-margin="three-quarters">
This will animate when it's 75% from the bottom of the viewport
</div>You can also use raw CSS margin values if you need more precise control:
<divdata-murphy="bottom-to-top" data-murphy-root-margin="0px 0px -50% 0px">
This will animate when it reaches the middle of the viewport
</div>The root margin follows the CSS margin syntax: top right bottom left. Negative values create an inset margin, which means the animation will trigger when the element reaches that point in the viewport.
| Alias | Description | Raw Value |
|---|---|---|
top | Triggers at top of viewport | '0px 0px 0px 0px' |
middle | Triggers at middle of viewport | '0px 0px -50% 0px' |
bottom | Triggers at bottom of viewport | '0px 0px 0px 0px' |
quarter | Triggers at 25% from bottom | '0px 0px -25% 0px' |
three-quarters | Triggers at 75% from bottom | '0px 0px -75% 0px' |
You can group elements using the data-murphy-group attribute. This allows you to control animations for specific groups of elements. For example, you can play or reset animations for only a subset of elements by specifying a group name:
<divdata-murphy="bottom-to-top" data-murphy-group="group1">Group 1</div><divdata-murphy="top-to-bottom" data-murphy-group="group1">Group 1</div><divdata-murphy="left-to-right" data-murphy-group="group2">Group 2</div><divdata-murphy="right-to-left" data-murphy-group="group2">Group 2</div>You can then control animations for a specific group using the API:
// Play animations for group1 onlymurphy.play('group1');// Reset animations for group2 onlymurphy.reset('group2');| Method | Description |
|---|---|
play(group?: string) | Start monitoring elements in DOM tagged with data-murphy attribute. Optionally specify a group to animate only elements in that group. |
cancel() | Cancel all animations and reset elements to their final state. |
reset(group?: string) | Reset all animations to their initial state. Optionally specify a group to reset only elements in that group. |
cleanup() | Disconnect all Intersection Observers and clean up resources. |
The Murphy class provides a programmatic way to create animations:
import{Murphy}from'murphyjs';// Create a new instanceconstmurphy=newMurphy();// Animate elementsmurphy.animate('.box',{opacity: [0,1],y: [20,0],duration: 1000});Animates elements matching the selector with the specified options.
| Parameter | Type | Description |
|---|---|---|
selector | String | CSS selector for target elements |
options | Object | Animation configuration |
| Option | Type | Default | Description |
|---|---|---|---|
opacity | Array | [0, 1] | Start and end opacity values |
x | Array | [0, 0] | Start and end x translation in pixels |
y | Array | [0, 0] | Start and end y translation in pixels |
duration | Number | 1000 | Animation duration in milliseconds |
delay | Number | 0 | Delay before animation starts in milliseconds |
ease | String | 'ease' | Easing function name |
MurphyJS provides a set of events that you can listen to for better control and integration:
| Event | Description |
|---|---|
murphy:in | Fired when an element enters the viewport |
murphy:out | Fired when an element leaves the viewport |
murphy:finish | Fired when an animation completes |
murphy:cancel | Fired when an animation is cancelled |
murphy:reset | Fired when an element is reset |
murphy:cleanup | Fired when observers are cleaned up |
document.addEventListener('murphy:in',(event)=>{const{ element }=event.detail;console.log('Element entered viewport:',element);});document.addEventListener('murphy:finish',(event)=>{const{ element }=event.detail;console.log('Animation finished:',element);});MurphyJS comes with several built-in animations that you can use with the data-murphy attribute:
bottom-to-toptop-to-bottomleft-to-rightright-to-left
flip-leftflip-rightflip-upflip-down
zoom-inzoom-out
fadefade-upfade-downfade-leftfade-right
rotate-leftrotate-right
scale-upscale-down
slide-upslide-downslide-leftslide-right
bounce-inbounce-out
