animejs

When writing JavaScript animations using anime.js v4, including DOM element animations, timelines, stagger effects, scroll-triggered animations, SVG animations, text animations, draggable elements, layout transitions, or any motion/transition effects on websites. Also use when the user says "animate," "animation library," "anime.js," "stagger," "timeline animation," "scroll animation," "text animation," "draggable," or "motion effects."

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "animejs" with this command: npx skills add almeidamarcell/claude-code-skills/almeidamarcell-claude-code-skills-animejs

anime.js v4 Animation

You are an expert in anime.js v4 (latest: v4.3.5), the lightweight JavaScript animation library. Generate production-ready animation code using the v4 API exclusively. Never use v3 syntax.

CRITICAL: v4 API Only

anime.js v4 introduced breaking changes from v3. ALWAYS use v4 syntax:

NEVER use (v3)ALWAYS use (v4)
anime({ targets: '.el', ... })animate('.el', { ... })
anime.timeline()createTimeline()
anime.stagger()stagger()
easing: 'easeOutQuad'ease: 'outQuad'
begin: fnonBegin: fn
change: fnonUpdate: fn
complete: fnonComplete: fn
direction: 'alternate'alternate: true
direction: 'reverse'reversed: true
endDelayloopDelay
anime.path()svg.createMotionPath()
anime.setDashoffset()svg.createDrawable()
animation.finished.then()animation.then()

Installation & Setup

CDN:

<script src="https://cdn.jsdelivr.net/npm/animejs@4/lib/anime.iife.min.js"></script>

npm:

npm install animejs

ES Module imports (recommended):

import { animate, stagger, createTimeline } from 'animejs';
// Additional features — import only what you need:
import { createAnimatable } from 'animejs';
import { createDraggable } from 'animejs';
import { createLayout } from 'animejs';
import { onScroll } from 'animejs';
import { waapi } from 'animejs';
import { svg } from 'animejs';
import { splitText } from 'animejs';
import { engine, utils } from 'animejs';

Subpath imports (tree-shaking):

import { animate } from 'animejs/animation';
import { createTimeline } from 'animejs/timeline';
import { createDraggable } from 'animejs/draggable';
import { onScroll } from 'animejs/events';
import { splitText } from 'animejs/text';

Core: animate(targets, parameters)

Targets

// CSS selector
animate('.box', { ... });

// DOM element
animate(document.querySelector('#hero'), { ... });

// Multiple elements (NodeList, Array)
animate(document.querySelectorAll('.card'), { ... });

// JavaScript object (animate numeric properties)
const obj = { progress: 0 };
animate(obj, { progress: 100, onUpdate: () => console.log(obj.progress) });

Parameters

ParameterTypeDefaultDescription
durationnumber1000Milliseconds
delaynumber/function0Delay before start
easestring/function'outQuad'Easing function
loopnumber/booleanfalsetrue = infinite, number = repeat count
loopDelaynumber0Delay between loops
alternatebooleanfalseReverse direction each loop
reversedbooleanfalsePlay backwards
autoplaybooleantrueStart immediately
frameRatenumber-Limit FPS
playbackRatenumber1Speed multiplier (2 = double speed)
compositionstring'replace''replace', 'add', 'blend'
modifierfunction-Transform animated value before applying

Callbacks

animate('.el', {
  translateX: 250,
  onBegin: (anim) => {},      // When animation starts (after delay)
  onUpdate: (anim) => {},     // Every frame
  onComplete: (anim) => {},   // When animation finishes
  onLoop: (anim) => {},       // After each loop iteration
  onPause: (anim) => {},      // When paused
}).then((anim) => {});         // Promise-based completion

Playback Controls

const anim = animate('.el', { translateX: 250, autoplay: false });

anim.play();        // Play forward
anim.pause();       // Pause
anim.resume();      // Resume from current position and direction
anim.reverse();     // Reverse direction
anim.restart();     // Restart from beginning
anim.seek(500);     // Jump to 500ms
anim.reset();       // Reset to initial values
anim.complete();    // Jump to end
anim.cancel();      // Cancel and clean up
anim.revert();      // Revert targets to original values

Animatable Properties

animate('.el', {
  // CSS transforms
  translateX: 250,
  translateY: 100,
  rotate: '1turn',
  scale: 1.5,
  skewX: '15deg',

  // CSS properties
  opacity: [0, 1],
  backgroundColor: '#FF0000',
  borderRadius: '50%',
  width: '200px',

  // CSS variables
  '--custom-prop': 100,

  // Relative values
  translateX: '+=100',
  rotate: '-=45deg',

  // From-to syntax
  opacity: { from: 0, to: 1 },
  translateY: [50, 0],          // [from, to]

  // Per-property parameters
  translateX: { to: 250, duration: 800, ease: 'outExpo' },
  opacity: { to: 1, duration: 400, delay: 200 },

  // Function-based values (per target)
  translateX: (target, index, total) => index * 50,
  delay: (target, index) => index * 100,
});

Keyframes

Property-level (array of values):

animate('.el', {
  translateX: [0, 100, 50, 200],
  duration: 2000,
});

Property-level (array of objects):

animate('.el', {
  translateX: [
    { to: 100, duration: 500, ease: 'outQuad' },
    { to: 50, duration: 300 },
    { to: 200, duration: 700, ease: 'inOutCubic' },
  ],
});

Percentage-based:

animate('.el', {
  keyframes: {
    '0%':   { translateX: 0, opacity: 0 },
    '40%':  { translateX: 100, opacity: 1 },
    '100%': { translateX: 250, opacity: 0.5 },
  },
  duration: 2000,
});

Stagger

Distribute values or delays across multiple targets.

import { animate, stagger } from 'animejs';

// Basic delay stagger: each element starts 100ms after the previous
animate('.card', {
  opacity: [0, 1],
  translateY: [30, 0],
  delay: stagger(100),
  duration: 500,
  ease: 'outCubic',
});

// From center outward
animate('.item', { scale: [0, 1], delay: stagger(80, { from: 'center' }) });

// From edges inward
animate('.item', { scale: [0, 1], delay: stagger(80, { from: 'edges' }) });

// From specific index
animate('.item', { scale: [0, 1], delay: stagger(80, { from: 3 }) });

// Range distribution: values spread evenly between 0 and 200
animate('.item', { translateX: stagger([0, 200]) });

// Grid stagger (rows x cols)
animate('.grid-item', {
  scale: [0, 1],
  delay: stagger(50, { grid: [4, 6], from: 'center', axis: 'y' }),
});

// Eased stagger distribution
animate('.item', { opacity: [0, 1], delay: stagger(300, { ease: 'inOutQuad' }) });

Timelines

Sequence and synchronize multiple animations.

import { createTimeline, stagger } from 'animejs';

const tl = createTimeline({
  defaults: { duration: 600, ease: 'outQuad' },
});

// Animations chain sequentially by default
tl.add('.header', { opacity: [0, 1], translateY: [-30, 0] })
  .add('.subtitle', { opacity: [0, 1], translateY: [20, 0] }, '-=300')  // Overlap by 300ms
  .add('.cta-btn', { opacity: [0, 1], scale: [0.8, 1] }, '+=100')      // 100ms gap
  .add('.cards', {
    opacity: [0, 1],
    translateY: [40, 0],
    delay: stagger(80),
  }, '-=200');

// Absolute positioning (ms from timeline start)
tl.add('.bg', { opacity: [0, 0.5] }, 0);  // Starts at 0ms

// Timeline controls
tl.play();
tl.pause();
tl.seek(1000);
tl.reverse();
tl.restart();

Text Splitting

Split text into lines, words, or characters for per-element animation.

import { splitText, animate, stagger } from 'animejs';

// Split heading into characters
const splitter = splitText('.hero-title', {
  chars: true,          // Split into characters
  // words: true,       // Split into words
  // lines: true,       // Split into lines
  accessible: true,     // Maintain screen reader accessibility
});

// Animate each character
animate(splitter.chars, {
  opacity: [0, 1],
  translateY: [20, 0],
  delay: stagger(30),
  duration: 400,
  ease: 'outCubic',
});

// Revert DOM to original text when done
// splitter.revert();

Scroll Observer

Trigger and synchronize animations with scroll position.

import { animate, onScroll } from 'animejs';

// Trigger animation when element enters viewport
onScroll('.section', {
  onEnter: () => {
    animate('.section .content', {
      opacity: [0, 1],
      translateY: [40, 0],
      duration: 800,
      ease: 'outQuad',
    });
  },
});

// Directional callbacks
onScroll('.element', {
  onEnterForward: () => {},    // Scrolling down into view
  onEnterBackward: () => {},   // Scrolling up into view
  onLeaveForward: () => {},    // Scrolling down out of view
  onLeaveBackward: () => {},   // Scrolling up out of view
});

// Sync animation progress to scroll position
const anim = animate('.parallax-bg', {
  translateY: [-100, 100],
  autoplay: false,
});

onScroll('.parallax-section', {
  sync: 'playback',    // Links scroll position to animation progress
  link: anim,
});

// Thresholds
onScroll('.el', {
  enter: 'top bottom',     // When top of el crosses bottom of viewport
  leave: 'bottom top',     // When bottom of el crosses top of viewport
});

WAAPI (Web Animation API)

Lightweight 3KB alternative using browser-native Web Animation API. Hardware-accelerated. Use for simple animations where performance is critical.

import { waapi } from 'animejs';

const anim = waapi.animate('.el', {
  translateX: 250,
  opacity: [0, 1],
  duration: 600,
  ease: 'outQuad',
});

When to use WAAPI vs full animate():

  • WAAPI: Simple CSS transforms/opacity, high-performance needs, many simultaneous elements
  • Full animate(): JS object animation, complex keyframes, onUpdate callback, modifier functions, SVG features

Animatable

Reactive value animation — ideal for cursor tracking, interactive UIs, and frequently changing values.

import { createAnimatable } from 'animejs';

const follower = createAnimatable('.cursor-follower', {
  x: { duration: 300, ease: 'outQuad' },
  y: { duration: 300, ease: 'outQuad' },
});

document.addEventListener('mousemove', (e) => {
  follower.x(e.clientX);  // Setter: animates to value
  follower.y(e.clientY);
});

// Getter
const currentX = follower.x();

Layout Animations

Animate layout changes that are normally impossible (CSS display, grid, flex, DOM order).

import { createLayout } from 'animejs';

const layout = createLayout('.container', {
  duration: 500,
  ease: 'outQuad',
  // Enter/exit states for added/removed elements
  enterFrom: { opacity: 0, scale: 0.8 },
  leaveTo: { opacity: 0, scale: 0.8 },
});

// Animate any layout change
layout.update(() => {
  // Toggle class, change display, reorder DOM, etc.
  container.classList.toggle('grid-view');
});

// Or manual record → animate pattern
layout.record();
// ... make DOM changes ...
layout.animate();

Draggable

Add drag interaction with physics.

import { createDraggable } from 'animejs';

const draggable = createDraggable('.card', {
  x: { snap: 100 },                // Snap to 100px grid on x-axis
  y: { snap: 100 },
  friction: 0.5,                    // Drag friction
  mass: 1,                          // Physics mass
  stiffness: 100,                   // Spring stiffness
  damping: 10,                      // Spring damping
  onGrab: (self) => {},
  onDrag: (self) => {},
  onRelease: (self) => {},
  onSnap: (self) => {},
  onSettle: (self) => {},
});

// Constrain to container
const draggable = createDraggable('.el', {
  container: '.bounds',
  x: true,
  y: true,
});

SVG Features

import { animate, svg } from 'animejs';

// Line drawing (animate stroke)
const drawable = svg.createDrawable('.svg-path');
animate(drawable, { draw: [0, 1], duration: 1500, ease: 'inOutQuad' });

// Shape morphing
animate('.shape path', {
  d: svg.morphTo('.target-shape path'),
  duration: 1000,
  ease: 'inOutQuad',
});

// Motion path (move element along SVG path)
const motionPath = svg.createMotionPath('.motion-path');
animate('.moving-element', {
  ...motionPath,         // Spread the path data
  duration: 3000,
  ease: 'linear',
  loop: true,
});

Easings

FamilyInOutInOut
QuadinQuadoutQuadinOutQuad
CubicinCubicoutCubicinOutCubic
QuartinQuartoutQuartinOutQuart
QuintinQuintoutQuintinOutQuint
SineinSineoutSineinOutSine
ExpoinExpooutExpoinOutExpo
CircinCircoutCircinOutCirc
BackinBackoutBackinOutBack
ElasticinElasticoutElasticinOutElastic

Custom easings:

ease: 'cubicBezier(0.25, 0.1, 0.25, 1.0)'   // CSS cubic-bezier
ease: 'spring(1, 100, 10, 0)'                 // spring(mass, stiffness, damping, velocity)
ease: 'steps(5)'                               // Stepped animation
ease: 'linear'                                 // Constant speed

When to use which:

  • Entrances: outQuad, outCubic, outExpo (fast start, slow end)
  • Exits: inQuad, inCubic (slow start, fast end)
  • State changes: inOutQuad, inOutCubic (smooth both ends)
  • Bouncy/playful: outBack, outElastic, spring()
  • Continuous/looping: linear

For the complete easing catalog with motion descriptions and presets, see references/easing-reference.md.


Engine Configuration

import { engine } from 'animejs';

engine.timeUnit = 'ms';          // 'ms' or 's'
engine.speed = 1;                // Global speed multiplier
engine.fps = 60;                 // Max frames per second
engine.precision = 4;            // Decimal precision
engine.pauseOnDocumentHidden = true;  // Pause when tab hidden

Utilities

import { utils } from 'animejs';

utils.get('.el', 'translateX');          // Get current value
utils.set('.el', { opacity: 0.5 });     // Set without animating
utils.random(0, 100);                   // Random number
utils.clamp(value, 0, 100);             // Clamp to range
utils.snap(value, 10);                  // Snap to nearest 10
utils.mapRange(value, 0, 1, 0, 100);    // Remap range
utils.lerp(start, end, 0.5);            // Linear interpolation

Selector shorthand:

import { $ } from 'animejs';
const elements = $('.card');  // Like querySelectorAll

Common Patterns

Fade in on load

animate('.element', {
  opacity: [0, 1],
  translateY: [20, 0],
  duration: 600,
  ease: 'outQuad',
});

Staggered list entrance

animate('.list-item', {
  opacity: [0, 1],
  translateY: [30, 0],
  delay: stagger(80),
  duration: 500,
  ease: 'outCubic',
});

Hover scale effect

document.querySelectorAll('.btn').forEach(btn => {
  btn.addEventListener('mouseenter', () =>
    animate(btn, { scale: 1.05, duration: 200, ease: 'outQuad' })
  );
  btn.addEventListener('mouseleave', () =>
    animate(btn, { scale: 1, duration: 200, ease: 'outQuad' })
  );
});

Loading spinner

animate('.spinner', {
  rotate: '1turn',
  duration: 800,
  loop: true,
  ease: 'linear',
});

Animated counter

const counter = { value: 0 };
animate(counter, {
  value: 2500,
  duration: 2000,
  ease: 'outExpo',
  onUpdate: () => {
    document.querySelector('.count').textContent = Math.round(counter.value);
  },
});

Scroll-triggered reveal

onScroll('.reveal-section', {
  onEnter: () => {
    animate('.reveal-section .item', {
      opacity: [0, 1],
      translateY: [40, 0],
      delay: stagger(100),
      duration: 600,
      ease: 'outCubic',
    });
  },
});

Text reveal

const splitter = splitText('.headline', { chars: true, accessible: true });
animate(splitter.chars, {
  opacity: [0, 1],
  translateY: [20, 0],
  delay: stagger(25),
  duration: 400,
  ease: 'outCubic',
});

Draggable card

createDraggable('.drag-card', {
  container: '.card-area',
  x: true,
  y: true,
  friction: 0.7,
  onRelease: (self) => {
    // Snap back or process drop
  },
});

For complete website animation patterns (hero sections, navigation effects, parallax, modals, carousels, etc.), see references/website-animation-patterns.md.


v3 to v4 Complete Migration Reference

v3 (NEVER use)v4 (ALWAYS use)
anime({ targets: '.el', ... })animate('.el', { ... })
anime.timeline({ ... })createTimeline({ ... })
anime.stagger(100)stagger(100)
easing: 'easeOutQuad'ease: 'outQuad'
easing: 'easeInOutExpo'ease: 'inOutExpo'
begin: fnonBegin: fn
change: fnonUpdate: fn
complete: fnonComplete: fn
changeBegin: fnRemoved — use onBegin
changeComplete: fnRemoved — use onComplete
direction: 'alternate'alternate: true
direction: 'reverse'reversed: true
endDelay: 500loopDelay: 500
anime.remove(targets)anim.revert()
anime.path('.path')svg.createMotionPath('.path')
anime.setDashoffset(el)svg.createDrawable(el)
animation.finished.then(fn)animation.then(fn)
value: 100 (in keyframe objects)to: 100
import anime from 'animejs'import { animate } from 'animejs'

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

entire

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

brand-guidelines

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

changelog-generator

No summary provided by upstream source.

Repository SourceNeeds Review