MotionFlow logo

Scroll Animations

Animate elements as they enter the viewport using simple HTML attributes. Create fades, slides, zooms, flips, rotations, and more — with full control over timing, easing, delay, and repeat behavior.

# Getting started

MotionFlow works out of the box. Simply include the MotionFlow CSS and JavaScript files, then start using data-mf-animation attributes in your HTML.

No initialization required. No configuration required. No JavaScript required.

Demo
I animate on scroll
<div data-mf-animation="fade-up">I animate on scroll</div>

MotionFlow automatically detects these attributes and applies animations when elements enter the viewport.

# Animation attributes

MotionFlow is attribute-first. All animation behavior can be controlled directly from HTML using data-mf-* attributes, without any JavaScript configuration.

Demo
All animation attributes
<div 
 data-mf-animation="fade-up"
 data-mf-animation-duration="600"
 data-mf-animation-delay="0"
 data-mf-animation-distance="100"
 data-mf-animation-easing="ease"
 data-mf-animation-once="false"
 data-mf-animation-repeat="both"
 data-mf-animation-trigger="top 90%"
>
  All animation attributes 
</div>

You don’t need to add every attribute. MotionFlow has default values for all attributes. Default values are listed in the table below. Add an attribute only when you want to override the default.

AttributeDefaultDescription
data-mf-animationDefines the animation preset applied when the element enters the viewport
data-mf-animation-duration600Duration of the animation in milliseconds
data-mf-animation-delay0Delay before the animation starts after entering the viewport
data-mf-animation-distance100Controls how far the element moves during the animation (in pixels)
data-mf-animation-easingeaseControls the timing curve using MotionFlow easing presets
data-mf-animation-oncefalseRuns the animation only the first time the element appears
data-mf-animation-repeatbothControls how the animation resets when leaving and re-entering the viewport
data-mf-animation-triggertop 90%Defines when the animation starts relative to the viewport position

# Animation types

MotionFlow includes a set of built-in animation presets that control how elements visually enter the viewport. These presets are applied using the data-mf-animation attribute.

Demo
Fade up
Zoom in
Rotate
Hinge
<div data-mf-animation="fade-up">Fade up</div>
<div data-mf-animation="zoom-in">Zoom in</div>
<div data-mf-animation="rotate">Rotate</div>
<div data-mf-animation="hinge">Hinge</div>
AnimationUsageDescription
fadedata-mf-animation="fade"Simple fade in with no movement
fade-updata-mf-animation="fade-up"Fades in while moving upward
fade-downdata-mf-animation="fade-down"Fades in while moving downward
fade-leftdata-mf-animation="fade-left"Fades in while moving from left
fade-rightdata-mf-animation="fade-right"Fades in while moving from right
fade-up-leftdata-mf-animation="fade-up-left"Fades in from bottom-left
fade-up-rightdata-mf-animation="fade-up-right"Fades in from bottom-right
fade-down-leftdata-mf-animation="fade-down-left"Fades in from top-left
fade-down-rightdata-mf-animation="fade-down-right"Fades in from top-right
slide-updata-mf-animation="slide-up"Slides upward into view
slide-downdata-mf-animation="slide-down"Slides downward into view
slide-leftdata-mf-animation="slide-left"Slides in from left
slide-rightdata-mf-animation="slide-right"Slides in from right
zoom-indata-mf-animation="zoom-in"Scales up while fading in
zoom-outdata-mf-animation="zoom-out"Scales down while fading in
zoom-in-updata-mf-animation="zoom-in-up"Zooms in from bottom
zoom-in-downdata-mf-animation="zoom-in-down"Zooms in from top
zoom-in-leftdata-mf-animation="zoom-in-left"Zooms in from left
zoom-in-rightdata-mf-animation="zoom-in-right"Zooms in from right
zoom-out-updata-mf-animation="zoom-out-up"Zooms out upward
zoom-out-downdata-mf-animation="zoom-out-down"Zooms out downward
zoom-out-leftdata-mf-animation="zoom-out-left"Zooms out to left
zoom-out-rightdata-mf-animation="zoom-out-right"Zooms out to right
flip-updata-mf-animation="flip-up"Flips upward along X-axis
flip-downdata-mf-animation="flip-down"Flips downward along X-axis
flip-leftdata-mf-animation="flip-left"Flips from left along Y-axis
flip-rightdata-mf-animation="flip-right"Flips from right along Y-axis
rotatedata-mf-animation="rotate"Rotates into place
rotate-up-leftdata-mf-animation="rotate-up-left"Rotates upward from left
rotate-up-rightdata-mf-animation="rotate-up-right"Rotates upward from right
rotate-down-leftdata-mf-animation="rotate-down-left"Rotates downward from left
rotate-down-rightdata-mf-animation="rotate-down-right"Rotates downward from right
blurdata-mf-animation="blur"Fades in while removing blur
blur-updata-mf-animation="blur-up"Blurs + fades in while moving upward
blur-downdata-mf-animation="blur-down"Blurs + fades in while moving downward
blur-leftdata-mf-animation="blur-left"Blurs + fades in while moving from left
blur-rightdata-mf-animation="blur-right"Blurs + fades in while moving from right
hingedata-mf-animation="hinge"Hinged rotation from the top (center origin)
hinge-leftdata-mf-animation="hinge-left"Hinged rotation from top-left corner
hinge-rightdata-mf-animation="hinge-right"Hinged rotation from top-right corner
lightspeed-leftdata-mf-animation="lightspeed-left"Fast skewed slide-in from left
lightspeed-rightdata-mf-animation="lightspeed-right"Fast skewed slide-in from right
roll-leftdata-mf-animation="roll-left"Rolls in from left while rotating
roll-rightdata-mf-animation="roll-right"Rolls in from right while rotating
back-in-updata-mf-animation="back-in-up"Enters from below, pauses briefly, then scales to full size
back-in-downdata-mf-animation="back-in-down"Enters from above, pauses briefly, then scales to full size
back-in-leftdata-mf-animation="back-in-left"Enters from the left, pauses briefly, then scales to full size
back-in-rightdata-mf-animation="back-in-right"Enters from the right, pauses briefly, then scales to full size
bouncedata-mf-animation="bounce"Bounces into place with subtle vertical movement
bounce-updata-mf-animation="bounce-up"Bounces upward from below the viewport
bounce-downdata-mf-animation="bounce-down"Bounces downward from above the viewport
bounce-leftdata-mf-animation="bounce-left"Bounces in from the left side
bounce-rightdata-mf-animation="bounce-right"Bounces in from the right side
bounce-scaledata-mf-animation="bounce-scale"Bounces using scale only (no directional movement)
bounce-rotatedata-mf-animation="bounce-rotate"Bounces into place with rotation and scaling

# Animation duration

Control how long an animation takes to complete using the data-mf-animation-duration attribute. The value is defined in milliseconds.

Demo
Slow animation
<div
 data-mf-animation="fade-up"
 data-mf-animation-duration="1500"
>
Slow animation
</div>

Higher values result in slower, smoother animations, while lower values create snappier transitions. Duration applies to all animation presets consistently.

AttributeDefaultDescription
data-mf-animation-duration600Duration of the animation in milliseconds

# Animation delay

Control when an animation starts after the element enters the viewport using the data-mf-animation-delay attribute. The value is defined in milliseconds.

Demo
Delayed animation
<div
data-mf-animation="fade-up"
data-mf-animation-delay="400"
>
 Delayed animation
</div>

Delay affects only the start time of an animation — it does not change animation speed. This is useful for creating staggered layouts, visual rhythm, and controlled motion sequences.

AttributeDefaultDescription
data-mf-animation-delay0Delay before animation starts (milliseconds)

# Animation distance

Control how far an element moves during an animation using the data-mf-animation-distance attribute. The value is defined in pixels.

Demo
Larger movement
<div
data-mf-animation="fade-up"
data-mf-animation-distance="200"
>
 Larger movement
</div>

Distance controls the starting offset of an animation. Higher values create more dramatic motion, while lower values result in subtle, minimal movement. Distance applies consistently across all directional animation presets.

AttributeDefaultDescription
data-mf-animation-distance100Distance (in pixels) the element travels during animation

# Animation easing

Control the timing curve of animations using the data-mf-animation-easing attribute. Easing defines how the animation accelerates and slows down over time.

Demo
Smooth easing
<div
data-mf-animation="fade-up"
data-mf-animation-easing="ease-out-back"
>
 Smooth easing
</div>

Easing affects the feel of motion. Linear easings feel mechanical, while curved easings feel more natural and polished. MotionFlow supports a rich set of predefined easing presets.

AttributeDefaultDescription
data-mf-animation-easingeaseCSS easing function controlling animation timing

## Built-in easing presets

MotionFlow provides a set of predefined easing presets that can be applied directly using the data-mf-animation-easing attribute. Choose the preset name and add it to your HTML — no custom curves required.

Easing presetUsage
lineardata-mf-animation-easing="linear"
easedata-mf-animation-easing="ease"
ease-indata-mf-animation-easing="ease-in"
ease-outdata-mf-animation-easing="ease-out"
ease-in-outdata-mf-animation-easing="ease-in-out"
ease-in-backdata-mf-animation-easing="ease-in-back"
ease-out-backdata-mf-animation-easing="ease-out-back"
ease-in-out-backdata-mf-animation-easing="ease-in-out-back"
ease-in-sinedata-mf-animation-easing="ease-in-sine"
ease-out-sinedata-mf-animation-easing="ease-out-sine"
ease-in-out-sinedata-mf-animation-easing="ease-in-out-sine"
ease-in-quaddata-mf-animation-easing="ease-in-quad"
ease-out-quaddata-mf-animation-easing="ease-out-quad"
ease-in-out-quaddata-mf-animation-easing="ease-in-out-quad"
ease-in-cubicdata-mf-animation-easing="ease-in-cubic"
ease-out-cubicdata-mf-animation-easing="ease-out-cubic"
ease-in-out-cubicdata-mf-animation-easing="ease-in-out-cubic"
ease-in-quartdata-mf-animation-easing="ease-in-quart"
ease-out-quartdata-mf-animation-easing="ease-out-quart"
ease-in-out-quartdata-mf-animation-easing="ease-in-out-quart"
ease-in-quintdata-mf-animation-easing="ease-in-quint"
ease-out-quintdata-mf-animation-easing="ease-out-quint"
ease-in-out-quintdata-mf-animation-easing="ease-in-out-quint"
ease-in-expodata-mf-animation-easing="ease-in-expo"
ease-out-expodata-mf-animation-easing="ease-out-expo"
ease-in-out-expodata-mf-animation-easing="ease-in-out-expo"
ease-in-circdata-mf-animation-easing="ease-in-circ"
ease-out-circdata-mf-animation-easing="ease-out-circ"
ease-in-out-circdata-mf-animation-easing="ease-in-out-circ"
ease-in-elasticdata-mf-animation-easing="ease-in-elastic"
ease-out-elasticdata-mf-animation-easing="ease-out-elastic"
ease-in-out-elasticdata-mf-animation-easing="ease-in-out-elastic"
ease-in-bouncedata-mf-animation-easing="ease-in-bounce"
ease-out-bouncedata-mf-animation-easing="ease-out-bounce"
ease-in-out-bouncedata-mf-animation-easing="ease-in-out-bounce"

# Run animation once

By default, scroll animations replay when elements re-enter the viewport. Use the data-mf-animation-once attribute to run an animation only the first time it appears.

Demo
Animate only once
<div
  data-mf-animation="fade-up"
  data-mf-animation-once="true"
>
  Animate only once
</div>

When data-mf-animation-once="true" is set, the animation will not replay even if the element leaves and re-enters the viewport.

AttributeDefaultDescription
data-mf-animation-oncefalseRun animation only the first time the element enters the viewport

# Repeat behavior

Control how animations behave when elements leave and re-enter the viewport using the data-mf-animation-repeat attribute. Repeat behavior only applies when data-mf-animation-once is set to false.

Demo
Re-animates on scroll
<div
  data-mf-animation="fade-up"
  data-mf-animation-repeat="both"
>
  Re-animates on scroll
</div>

The data-mf-animation-repeat attribute controls how an animation replays when an element leaves and re-enters the viewport. The animation always runs once on first entry, and repeat behavior applies only when data-mf-animation-once="false".

AttributeDefaultDescription
data-mf-animation-repeatbothControls how the animation replays when entering and leaving the viewport

Repeat values

ValueUsageDescription
bothdata-mf-animation-repeat="both"Re-runs the animation when the element re-enters the viewport from either direction
topdata-mf-animation-repeat="top"Animate only when scrolling down into view
bottomdata-mf-animation-repeat="bottom"Animate only when scrolling back up into view

# Trigger position

Control when an animation should start as an element enters the viewport using the data-mf-animation-trigger attribute. The trigger defines the relationship between the element’s position and the viewport.

Demo
Triggered at 70% viewport
<div
data-mf-animation="fade-up"
data-mf-animation-trigger="top 70%"
>
 Triggered at 70% viewport
</div>

The data-mf-animation-trigger attribute defines when an animation should start by comparing a position on the element with a position inside the viewport.

It follows this format: element-position viewport-position and when the specified point on the element intersects the specified point in the viewport, the animation is triggered.

AttributeDefaultDescription
data-mf-animation-triggertop 90%Defines when the animation should start relative to the viewport

## Common trigger examples

Trigger valueWhat it means
top 70%The animation starts when the top of the element reaches 70% down the viewport height.
top centerThe animation starts when the top of the element aligns with the center of the viewport.
center centerThe animation starts when the center of the element reaches the center of the viewport.
bottom 90%The animation starts when the bottom of the element reaches 90% of the viewport height.
center 100%The animation starts when the center of the element reaches the bottom edge of the viewport.
top 0%The animation starts immediately when the top of the element touches the top of the viewport.

# Stagger animations

Stagger animations allow multiple elements to animate one after another as they enter the viewport. Instead of applying animation settings to each element manually, MotionFlow lets you define stagger behavior on a parent container.

When the parent element reaches its scroll trigger point, MotionFlow starts animating each direct child sequentially. Animation, delay, and timing are automatically calculated — no JavaScript or manual delay calculation required.

Demo
Item One
Item Two
Item Three
<div
data-mf-stagger-animation="fade-up"
data-mf-stagger-gap="120"
>
  <div>Item One</div>
  <div>Item Two</div>
  <div>Item Three</div>
</div>

Stagger delay is calculated automatically using the formula:
final delay = staggerDelay + (index × staggerGap)

Stagger animations fully support scroll animation type, duration, delay, distance, easing, once, repeat behavior and trigger.


## Stagger attributes

Stagger animations are applied on a parent element and automatically propagate to its children.

AttributeDefaultDescription
data-mf-stagger-animationAnimation type applied to each direct child
data-mf-stagger-delay0Base delay (in milliseconds) before the first child animates
data-mf-stagger-gap100Delay gap (in milliseconds) added between each child animation
data-mf-stagger-distance100Animation distance (in pixels) for all children
data-mf-stagger-duration600Animation duration (ms) for all children
data-mf-stagger-easingeaseEasing function applied to all children
data-mf-stagger-oncefalseAnimate children only once
data-mf-stagger-repeatbothControls when the stagger group resets (top, bottom, both)
data-mf-stagger-triggertop 90%Scroll trigger point for the entire stagger group

To exclude a specific child from the stagger sequence, add data-mf-stagger-ignore to that element.

Only direct children of the stagger container are animated. Children with their own data-mf-animationattribute are automatically skipped.

# Scroll animation lifecycle

Scroll animations work automatically in most cases. When elements are shown, hidden, or added dynamically, you may need manual control.

MethodMethod callDescription
initMotionFlow.scroll.init();Initializes or re-initializes scroll animations using the last configuration
refreshMotionFlow.scroll.refresh();Recalculates scroll trigger positions without restarting animations
destroyMotionFlow.scroll.destroy();Destroys scroll animations without affecting other modules

## Example usage

When scroll-animated elements become visible dynamically, refresh the scroll engine after the layout update.

// Call this after content becomes visible or layout changes
function onLayoutChange() {
  MotionFlow.scroll.refresh();
}

# Global configuration (optional)

MotionFlow does not require any JavaScript configuration to work. However, you can define global defaults if you want to override the default values or avoid repeating the same attributes across multiple elements.

Individual elements can still override these settings using data-mf-* attributes.

MotionFlow.init({
  animation: {
    /* --------------------------------------------------
       Base Scroll Animations (for [data-mf-animation])
    ----------------------------------------------------- */
    duration: 600,       // Default: 600       | Animation duration in milliseconds
    delay: 0,            // Default: 0         | Delay before animation starts (ms)
    distance: 100,       // Default: 100       |  Translate distance in pixels
    easing: "ease",      // Default: "ease"    |  Built-in MotionFlow easing presets
    once: false,         // Default: false     |  true  → animate only once  // false → animate every time element enters viewport
    repeat: "both",      // Default: "both"    |  Values: top | bottom | both  //  Reset animation when leaving viewport
    trigger: "top 90%",  // Default: "top 90%" |  Format: <element-anchor> <viewport-anchor> // Element anchor: top | center | bottom // Viewport anchor: % | top | center | bottom
    /* --------------------------------------------------
       Stagger Scroll Animations (for [data-mf-stagger-animation])
       - Applied on parent  - Automatically propagates to direct children 
    ----------------------------------------------------- */
    stagger: {
      delay: 0,          // Default: 0         |  Base delay before first child animates (ms)
      gap: 100,          // Default: 100       |  Delay gap between staggered children (ms)
      duration: 600,     // Default: 600       |  Duration override for stagger items (ms)
      distance: 100,     // Default: 100       |  Distance override for stagger items (px)
      easing: "ease",    // Default: "ease"    |  Easing override for stagger items
      once: false,       // Default: false     |  true  → animate stagger items only once // false → animate on every scroll entry
      repeat: "both",    // Default: "both"    |  Reset behavior for stagger group
      trigger: "top 90%" // Default: "top 90%" |  Scroll trigger override for stagger group
    }
  }
});

If you don’t call MotionFlow.init(), MotionFlow uses built-in defaults automatically.