A+ animation module for the modern web
Animate Plus is a JavaScript animation library focusing on performance and authoring flexibility. It
aims to deliver a steady 60 FPS and weighs less than 3 KB (minified and compressed), making it particularly well-suited for mobile.
npm install animateplus
or download animateplus.js
and start animating things:
import animate from "/animateplus.js";
animate({
elements: "div",
duration: 2000,
delay: index => index * 100,
transform: ["scale(0)", "scale(1)"]
})
.then(options => animate({
...options,
transform: ["translate(0%)", "translate(500%)"]
}));
Default | Type |
---|---|
null |
String | Element | NodeList | Array |
Determines the DOM elements to animate. You can either pass it a CSS selector or DOM elements.
animate({
elements: document.body.children,
transform: ["rotate(0turn)", "rotate(1turn)"]
});
Default | Type |
---|---|
out-elastic |
String |
Determines the acceleration curve of your animation.
constant | accelerate | decelerate | accelerate-decelerate |
---|---|---|---|
linear | in-cubic | out-cubic | in-out-cubic |
in-quartic | out-quartic | in-out-quartic | |
in-quintic | out-quintic | in-out-quintic | |
in-exponential | out-exponential | in-out-exponential | |
in-circular | out-circular | in-out-circular | |
in-elastic | out-elastic | in-out-elastic |
The amplitude and period of elastic easings can be configured by providing space-separated values.
Amplitude defaults to 1
, period to 0.4
.
// Increase elasticity
animate({
elements: "span",
easing: "out-elastic 1.4 0.2",
transform: ["translate(0px)", "translate(500px)"]
});
Default | Type |
---|---|
1000 |
Number | Function |
Determines the duration of your animation in milliseconds. By passing it a callback, you can define
a different duration for each element. The callback takes the index of each element as its argument
and returns a number.
// First element fades out in 1s, second element in 2s, etc.
animate({
elements: "span",
easing: "linear",
duration: index => (index + 1) * 1000,
opacity: [1, 0]
});
Default | Type |
---|---|
0 |
Number | Function |
Determines the delay of your animation in milliseconds. By passing it a callback, you can define
a different delay for each element. The callback takes the index of each element as its argument
and returns a number.
// First element fades out after 1s, second element after 2s, etc.
animate({
elements: "span",
easing: "linear",
delay: index => (index + 1) * 1000,
opacity: [1, 0]
});
Default | Type |
---|---|
false |
Boolean |
Determines if the animation should repeat.
Default | Type |
---|---|
normal |
String |
Determines the direction of the animation. reverse
runs the animation backwards, alternate
switches direction after each iteration if the animation loops.
Default | Type |
---|---|
1 |
Number |
Determines the animation playback rate. Useful in the authoring process to speed up some parts of a
long sequence (value above 1) or slow down a specific animation to observe it (value below 1).
Default | Type |
---|---|
false |
Boolean |
Forces hardware acceleration during an animation if set to true
. Unless you experience performance
issues, it’s recommended to leave it off as hardware acceleration comes with potentially harmful
side-effects.
Default | Type |
---|---|
null |
Object | Function |
Simulates a motion blur effect. Takes an object or a function returning an object that specifies the
strength of the directional blur on the x
and y
axes. A missing axis defaults to 0
, which
disables the blur on that axis.
animate({
elements: "circle",
easing: "out-exponential",
duration: 2500,
loop: true,
direction: "alternate",
blur: {x: 20, y: 2},
transform: ["translate(0%)", "translate(80%)"]
});
Default | Type |
---|---|
null |
Function |
Defines a callback invoked on every frame of the animation. The callback takes as its argument the
animation progress (between 0 and 1) and can be used on its own without being tied to elements
.
// Linearly outputs the percentage increase during 5s
animate({
duration: 5000,
easing: "linear",
change: progress =>
document.body.textContent = `${Math.round(progress * 100)}%`
});
Animate Plus lets you animate HTML and SVG elements with any property that takes numeric values,
including hexadecimal colors.
// Animate the radius and fill color of an SVG circle
animate({
elements: "circle",
r: [0, 50],
fill: ["#80f", "#fc0"]
});
Each property you animate needs an array defining the start and end values. For convenience, you can
omit everything but the numbers in the end values.
// Same as ["translate(0px)", "translate(100px)"]
animate({
elements: "span",
transform: ["translate(0px)", 100]
});
These arrays can optionally be returned by a callback that takes the index of each element, just
like with duration and delay.
// First element translates by 100px, second element by 200px, etc.
animate({
elements: "span",
transform: index => ["translate(0px)", (index + 1) * 100]
});
animate()
returns a promise which resolves once the animation finishes. The promise resolves to
the object initially passed to animate()
, making animation chaining straightforward and
convenient. The Getting started section gives you a basic promise example.
Since Animate Plus relies on native promises, you can benefit from all the usual features promises
provide, such as Promise.all
, Promise.race
, and especially async/await
which makes animation
timelines easy to set up.
const play = async () => {
const options = await animate({
elements: "span",
duration: 3000,
transform: ["translateY(-100vh)", 0]
});
await animate({
...options,
transform: ["rotate(0turn)", 1]
});
await animate({
...options,
duration: 800,
easing: "in-quintic",
transform: ["scale(1)", 0]
});
};
play();
Stops the animations on the elements passed as the argument.
import {stop} from "/animateplus.js";
animate({
elements: "span",
easing: "linear",
duration: index => 8000 + index * 200,
loop: true,
transform: ["rotate(0deg)", 360]
});
document.addEventListener("click", ({target}) => stop(target));
Sets a timer in milliseconds. It differentiates from setTimeout()
by returning a promise and being
more accurate, consistent and battery-friendly. The delay option relies internally on
this method.
import {delay} from "/animateplus.js";
delay(500).then(time => console.log(`${time}ms elapsed`));
Animate Plus is provided as a native ES2015 module, which means you may need to transpile it
depending on your browser support policy. The library works as is using <script type=module>
in
the following browsers:
Animate Plus is available on CDNJS and jsDelivr.
import animate from "https://cdn.jsdelivr.net/npm/animateplus@2/animateplus.js";
animate({
elements: "div",
transform: ["translate(0%)", 100]
});
Animations play a major role in the design of good user interfaces. They help connecting actions to
consequences, make the flow of interactions manifest, and greatly improve the polish and perception
of a product. However, animations can be damaging and detrimental to the user experience if they get
in the way. Here are a few best practices to keep your animations effective and enjoyable:
transform
and opacity
as these are the only propertiesmatchMedia("(prefers-reduced-motion)")
in JavaScript.mousemove
/touchmove
.clip-path
.change()
.change()
.