JS API
ScrollAnimationTimeline
A parent component that manages scroll-based animations for its children ScrollAnimationTarget components. The timeline watches for its position in the viewport and propagates the scroll progress to all its children.
This component is based on the withScrolledInView decorator from the @studiometa/js-toolkit package and inherits all of its options.
Usage
import { Base, createApp } from '@studiometa/js-toolkit';
import { ScrollAnimationTimeline, ScrollAnimationTarget } from '@studiometa/ui';
class App extends Base {
static config = {
name: 'App',
components: {
ScrollAnimationTimeline,
ScrollAnimationTarget,
},
};
}
export default createApp(App, document.body);<div data-component="ScrollAnimationTimeline">
<div
data-component="ScrollAnimationTarget"
data-option-from='{"opacity": 0}'
data-option-to='{"opacity": 1}'>
Content
</div>
</div>Options
debug
- Type:
boolean - Default:
false
Enable debug mode to display visual markers showing the scroll animation's start/end positions and current progress. This is useful during development to understand how the scroll animation is triggered.
WARNING
To use the debug option, you must wrap your ScrollAnimationTimeline with the withScrollAnimationDebug decorator. This allows the debug code to be tree-shaken from production bundles.
When enabled, the following elements are displayed:
- A dashed outline around the timeline element
- Start and end markers on the right side of the viewport
- A progress bar and percentage indicator
import { Base, createApp } from '@studiometa/js-toolkit';
import {
ScrollAnimationTimeline,
ScrollAnimationTarget,
withScrollAnimationDebug,
} from '@studiometa/ui';
class App extends Base {
static config = {
name: 'App',
components: {
ScrollAnimationTimeline: withScrollAnimationDebug(ScrollAnimationTimeline),
ScrollAnimationTarget,
},
};
}<div data-component="ScrollAnimationTimeline"
data-option-debug>
<div data-component="ScrollAnimationTarget" ...>
...
</div>
</div>offset
- Type:
string - Default:
"start end / end start"
Defines the limits used to calculate the progress of the scroll. The value is a string composed of two parts separated by a slash (/). Each part defines the point on which the progress calculation should be based.
<targetStart> <viewportStart> / <targetEnd> <viewportEnd>The default value start end / end start could be read as: calculate the progress of the target from when the start of the target crosses the end of the viewport to when the end of the target crosses the start of the viewport.
Each point accepts the following values:
- A number between
0and1 - A named string, either
start,endorcenterwhich will be mapped to values between0and1 - A string representing a CSS value with one of the following unit:
%,px,vw,vh,vmin,vmax
Common offset patterns:
| Offset | Description |
|---|---|
"start end / end start" | Default. Animation plays while element is visible in viewport |
"start center / end center" | Animation plays while element crosses the center of viewport |
"start start / end start" | Animation plays while element is at the top of viewport |
"start end / end end" | Animation plays while element is at the bottom of viewport |
"start start / end end" | Animation plays from when element enters until it completely leaves |
<div data-component="ScrollAnimationTimeline"
data-option-offset="start center / end center">
<div data-component="ScrollAnimationTarget" ...>
Animates as element crosses viewport center
</div>
</div>Children Components
ScrollAnimationTarget
- Type:
ScrollAnimationTarget[]
Array of child animation targets that will be animated based on the scroll progress of the timeline.
ScrollAnimationTarget
A component that animates based on scroll progress from a parent ScrollAnimationTimeline. Each target can have its own animation keyframes, play range, and damping settings.
Usage
<div data-component="ScrollAnimationTimeline">
<div
data-component="ScrollAnimationTarget"
data-option-from='{"opacity": 0, "y": 100}'
data-option-to='{"opacity": 1, "y": 0}'
data-option-play-range="[0, 0.5]">
First element
</div>
<div
data-component="ScrollAnimationTarget"
data-option-from='{"opacity": 0, "y": 100}'
data-option-to='{"opacity": 1, "y": 0}'
data-option-play-range="[0.5, 1]">
Second element
</div>
</div>Options
playRange
- Type:
[number, number] | [number, number, number] - Default:
[0, 1]
Define the scroll progress range when the animation should play. Values between 0 and 1, where 0 is when the timeline enters the viewport and 1 is when it exits.
<div data-component="ScrollAnimationTimeline">
<div
data-component="ScrollAnimationTarget"
data-option-play-range="[0, 0.5]">
First (animates from 0% to 50% scroll)
</div>
<div
data-component="ScrollAnimationTarget"
data-option-play-range="[0.5, 1]">
Second (animates from 50% to 100% scroll)
</div>
</div>Staggered animation
Staggered scroll animation can be created by giving 3 numbers to the playRange option:
index: the current index of the items in the staggered listlength: the length of the staggered itemsstep: the delay to apply between each item in the staggered list
<div data-component="ScrollAnimationTimeline">
<div
data-component="ScrollAnimationTarget"
data-option-play-range="[0, 2, 0.1]">
...
</div>
<div
data-component="ScrollAnimationTarget"
data-option-play-range="[1, 2, 0.1]">
...
</div>
</div>The following example uses Twig loop.index0 and loop.length variables to generate data-option-play-range attributes with a staggered effect.
Sequentially ordered animation
Use the [index, length, step] format for the data-option-play-range attribute value with a step value set to 1 / length to make each animation play sequentially.
from
- Type:
object - Default:
{}
Initial keyframe for the animation. Define CSS properties as key-value pairs.
<div data-component="ScrollAnimationTimeline">
<div
data-component="ScrollAnimationTarget"
data-option-from='{ "opacity": 0, "y": 100 }'>
...
</div>
</div>to
- Type:
object - Default:
{}
Final keyframe for the animation. Define CSS properties as key-value pairs.
<div data-component="ScrollAnimationTimeline">
<div
data-component="ScrollAnimationTarget"
data-option-to='{ "opacity": 1, "y": 0 }'>
...
</div>
</div>keyframes
- Type:
keyFrame[] - Default:
[]
Array of keyframes for complex animations. When provided, from and to are ignored.
<div data-component="ScrollAnimationTimeline">
<div
data-component="ScrollAnimationTarget"
data-option-keyframes='[
{ "--opacity": 0, "scale": 0.8 },
{ "--opacity": 0.5, "scale": 1.1 },
{ "--opacity": 1, "scale": 1 }
]'
style="opacity: var(--opacity, 0);">
...
</div>
</div>See the following types definitions and the animate documentation for more advanced documentation on keyframes.
import { TransformProps } from '@studiometa/js-toolkit/utils';
type EasingFunction = (value: number) => number;
type BezierCurve = [number, number, number, number];
type CSSCustomPropertyName = `--${string}`;
interface KeyFrame extends TransformProps {
opacity?: number;
transformOrigin?: string;
easing?: EasingFunction | BezierCurve;
offset?: number;
[key: CSSCustomPropertyName]: number;
}easing
- Type:
[number, number, number, number] - Default:
[0, 0, 1, 1]
Cubic-bezier easing values for the animation timing.
<div data-component="ScrollAnimationTimeline">
<div
data-component="ScrollAnimationTarget"
data-option-easing="[0.19, 1, 0.22, 1]">
...
</div>
</div>Common easing values
| Easing | Cubic bezier |
|---|---|
| Linear | [0, 0, 1, 1] |
| InBack | [0.6, -0.28, 0.735, 0.045] |
| InCirc | [0.6, 0.04, 0.98, 0.335] |
| InCubic | [0.55, 0.055, 0.675, 0.19] |
| InExpo | [0.95, 0.05, 0.795, 0.035] |
| InQuad | [0.55, 0.085, 0.68, 0.53] |
| InQuart | [0.895, 0.03, 0.685, 0.22] |
| InQuint | [0.755, 0.05, 0.855, 0.06] |
| InSine | [0.47, 0, 0.745, 0.715] |
| OutBack | [0.175, 0.885, 0.32, 1.275] |
| OutCirc | [0.075, 0.82, 0.165, 1] |
| OutCubic | [0.215, 0.61, 0.355, 1] |
| OutExpo | [0.19, 1, 0.22, 1] |
| OutQuad | [0.25, 0.46, 0.45, 0.94] |
| OutQuart | [0.165, 0.84, 0.44, 1] |
| OutQuint | [0.23, 1, 0.32, 1] |
| OutSine | [0.39, 0.575, 0.565, 1] |
| InOutBack | [0.68, -0.55, 0.265, 1.55] |
| InOutCirc | [0.785, 0.135, 0.15, 0.86] |
| InOutCubic | [0.645, 0.045, 0.355, 1] |
| InOutExpo | [1, 0, 0, 1] |
| InOutQuad | [0.455, 0.03, 0.515, 0.955] |
| InOutQuart | [0.77, 0, 0.175, 1] |
| InOutQuint | [0.86, 0, 0.07, 1] |
| InOutSine | [0.445, 0.05, 0.55, 0.95] |
dampFactor
- Type:
number - Default:
0.1
Damping factor for smooth scroll animations. Lower values create smoother, slower animations. Each ScrollAnimationTarget can have its own damping factor, allowing for different animation speeds within the same timeline.
<div data-component="ScrollAnimationTimeline">
<div
data-component="ScrollAnimationTarget"
data-option-damp-factor="0.05"
data-option-from='{"y": 100}'>
Slow and smooth
</div>
<div
data-component="ScrollAnimationTarget"
data-option-damp-factor="0.5"
data-option-from='{"y": 100}'>
Fast and snappy
</div>
</div>dampPrecision
- Type:
number - Default:
0.001
Precision threshold for damping calculations. Lower values increase precision but may impact performance.
Methods
render(progress)
- Parameters:
progress(number): animation progress between 0 and 1
- Returns:
void
Manually render the animation at a specific progress value.
Properties
target
- Type:
HTMLElement
The element being animated. Defaults to the component's root element ($el).
animation
- Type:
Animation
The animation instance created from the keyframes and easing options. See animate documentation.
dampedCurrent
- Type:
{ x: number, y: number }
Current damped scroll position values for both axes.
dampedProgress
- Type:
{ x: number, y: number }
Current damped progress values (0-1) for both axes.
playRange
- Type:
[number, number]
The computed play range for the animation, taking into account the staggered format if used.
ScrollAnimation (deprecated)
Deprecated
The ScrollAnimation component is deprecated. Use ScrollAnimationTimeline with ScrollAnimationTarget children instead.
A standalone component that watches its own position in the viewport and animates a target element. This component requires a target ref.
Usage
<div
data-component="ScrollAnimation"
data-option-from='{"opacity": 0, "y": 100}'
data-option-to='{"opacity": 1, "y": 0}'>
<div data-ref="target">Content to animate</div>
</div>Refs
target
- Type:
HTMLElement
The element to animate. Required for this component.
Options
The ScrollAnimation component supports the same options as ScrollAnimationTarget:
withScrollAnimationDebug
A decorator that adds debug capabilities to ScrollAnimationTimeline. When the debug option is enabled, it displays visual markers to help understand how the scroll animation is triggered.
This decorator is exported separately to allow tree-shaking the debug code from production bundles.
Usage
import { Base, createApp } from '@studiometa/js-toolkit';
import {
ScrollAnimationTimeline,
ScrollAnimationTarget,
withScrollAnimationDebug,
} from '@studiometa/ui';
class App extends Base {
static config = {
name: 'App',
components: {
ScrollAnimationTimeline: withScrollAnimationDebug(ScrollAnimationTimeline),
ScrollAnimationTarget,
},
};
}
export default createApp(App);<div data-component="ScrollAnimationTimeline" data-option-debug>
<div data-component="ScrollAnimationTarget" ...>
...
</div>
</div>Debug features
When the debug option is enabled on a ScrollAnimationTimeline component wrapped with this decorator:
- Outline: A dashed border around the timeline element
- Start marker: A horizontal line showing where in the viewport the animation starts
- End marker: A horizontal line showing where in the viewport the animation ends
- Progress indicator: A progress bar and percentage showing the current scroll progress
Each timeline gets a different color for easy identification when multiple timelines are on the same page.
Parameters
BaseClass(typeof ScrollAnimationTimeline): TheScrollAnimationTimelineclass to decorate
Return value
typeof ScrollAnimationTimeline: The decorated class with debug capabilities