# How to Create Staggered Animations Across Multiple Elements with Anime.js

> Learn to create staggered animations across multiple elements with Anime.js. Use the stagger function for automatic delay calculation and control easing and direction.

- Repository: [Julian Garnier/anime](https://github.com/juliangarnier/anime)
- Tags: how-to-guide
- Published: 2026-03-04

---

**Use the `stagger()` utility exported from `animejs` to generate per-element delays or property values that automatically calculate offsets based on each target's index, with optional support for grid layouts, easing curves, and directional control.**

Anime.js provides a declarative API for orchestrating complex motion, and the `stagger` utility defined in [`src/utils/stagger.js`](https://github.com/juliangarnier/anime/blob/main/src/utils/stagger.js) makes it trivial to **create staggered animations across multiple elements**. By passing `stagger()` as a property value in your animation configuration, you generate dynamic offsets that adapt to each element's position in the DOM collection, enabling everything from simple cascading delays to radial grid ripples without manual index calculations.

## Core Implementation and Algorithm

The stagger functionality lives in **[`src/utils/stagger.js`](https://github.com/juliangarnier/anime/blob/main/src/utils/stagger.js)**, where the `stagger(val, params = {})` function returns a callback that Anime.js invokes for each target during animation initialization. This callback receives the signature `(target, i, t, tl)` and computes the final value based on the element's position.

According to the source code in `juliangarnier/anime`, the internal algorithm performs six distinct steps:

1. **Determine the origin** (`from`) – defaults to the first element, but supports `'center'`, `'last'`, a numeric index, or `'random'`.
2. **Create the distance map** (`values`) on the first execution, calculating either linear indices or Euclidean distances when a `grid` is provided.
3. **Apply easing** (`staggerEase`) if an easing function or spring object is specified in `params.ease`.
4. **Reverse or shuffle** the distance map when `reversed: true` or `from: 'random'` is set.
5. **Scale the distances** to the user-provided step size (`val`) or range (`[min, max]`).
6. **Add the start offset** (`params.start`) and optional `modifier` function before returning the final number or string.

This pure function design allows the same stagger configuration to be reused across different properties—delay, translateX, opacity, or scale—within a single animation.

## Basic Delay Patterns

The most common use case for `stagger()` is creating incremental delays. Import `stagger` from `animejs` and pass it to the `delay` property.

### Simple Incremental Delays

```javascript
import { animate, stagger } from 'animejs';

animate('.item', {
  translateX: 100,
  duration: 800,
  delay: stagger(100),
  autoplay: true,
});

```

Each element receives a delay of `index × 100ms`, producing a sequence starting at 0ms, then 100ms, 200ms, and so on.

### Staggered Values with CSS Units

When passed a string with units, `stagger()` detects and preserves the unit suffix for each computed value.

```javascript
animate(document.querySelectorAll('#stagger div'), {
  translateX: stagger('1rem'),
  duration: 600,
});

```

This results in translateX values of `0rem`, `1rem`, `2rem`, etc., allowing unit-aware staggered positioning.

### Custom Start Offset

Use the `start` parameter to insert a base delay before the first element's offset begins.

```javascript
animate('.item', {
  translateX: 200,
  delay: stagger(50, { start: 200 }),
});

```

Here, the first element waits 200ms, while subsequent elements add 50ms increments (200ms, 250ms, 300ms...).

## Directional Control and Origin Points

By default, staggering proceeds from the first element to the last. The `from` and `reversed` parameters modify this directionality.

### Origin from the Center

Setting `from: 'center'` calculates offsets based on distance from the middle of the collection, creating symmetric ripple patterns.

```javascript
animate('.item', {
  translateX: 100,
  delay: stagger(80, { from: 'center' }),
});

```

Elements at the center receive the smallest delay, while peripheral elements wait longer.

### Reverse Order and Specific Indices

Start the sequence from a specific index or reverse the entire order.

```javascript
animate('.item', {
  translateX: 100,
  delay: stagger(60, { from: 1, reversed: true }),
});

```

This configuration begins at index 1 and counts backwards, effectively reversing the cascade direction.

## Easing Stagger Values

Apply easing curves to stagger offsets to create non-linear timing patterns, such as accelerations or decelerations across the element group.

```javascript
animate('.item', {
  translateX: 100,
  delay: stagger(120, { ease: 'inOutQuad' }),
});

```

Internally, `parseEase('inOutQuad')` produces a function that maps the linear distance to an easing curve, smoothing the delay distribution so elements cluster or spread according to the easing function's shape.

## Grid-Based Spatial Layouts

For two-dimensional arrangements, the `grid` and `axis` parameters calculate spatial distances rather than simple indices.

### Radial Grid Staggering

Treat elements as a matrix and stagger from the center outward.

```javascript
animate('#grid div', {
  scale: [1, 0],
  delay: stagger(30, { grid: [5, 3], from: 'center' })
});

```

With `grid: [5, 3]`, elements are treated as a 5-column by 3-row matrix. Distances compute from the grid center, yielding a radial ripple effect across the 2D plane.

### Axis-Specific Cascades

Restrict staggering to a single dimension using `axis: 'x'` or `axis: 'y'`.

```javascript
animate('#grid div', {
  translateX: stagger(20, { grid: [5, 3], axis: 'x' }),
  translateY: stagger(20, { grid: [5, 3], axis: 'y' })
});

```

This creates independent horizontal and vertical cascades, useful for wave-like effects that sweep across rows or columns specifically.

## Timeline Scheduling

In `createTimeline`, staggered offsets become part of the timeline's scheduling system, automatically extending the total duration.

```javascript
import { createTimeline, stagger } from 'animejs';

const tl = createTimeline({ defaults: { duration: 500 }, autoplay: false })
  .add('.item', { translateX: 200 }, stagger(150));

console.log(tl.duration); // total length = last offset + animation duration

```

The third argument to `.add()` accepts a stagger callback, positioning each element's animation start time according to the calculated offset while maintaining precise timeline control.

## Summary

- The **`stagger(val, params)`** function in [`src/utils/stagger.js`](https://github.com/juliangarnier/anime/blob/main/src/utils/stagger.js) returns a callback that computes per-element offsets based on index or grid position.
- **Basic syntax** supports numeric steps (`stagger(100)`) or unit strings (`stagger('1rem')`), with an optional `start` offset.
- **Directional control** uses `from: 'center' | 'last' | index` and `reversed: true` to change the animation origin and flow.
- **Easing** can be applied to stagger values via the `ease` parameter for non-linear timing distributions.
- **Grid staggering** treats elements as 2D matrices using `grid: [cols, rows]` and `axis: 'x' | 'y'` for spatial effects.
- **Timeline integration** allows staggered offsets to schedule animation start times within `createTimeline` instances.

## Frequently Asked Questions

### How does the stagger function determine the delay for each element?

The `stagger` function in [`src/utils/stagger.js`](https://github.com/juliangarnier/anime/blob/main/src/utils/stagger.js) determines delays by first building a distance map based on each element's index relative to the specified `from` origin (first element, center, last, or random). It scales these distances by the provided step value (`val`), applies optional easing or reversal, and adds the `start` offset. The result is returned as a callback that Anime.js executes for each target during animation initialization, as verified in [`tests/suites/stagger.test.js`](https://github.com/juliangarnier/anime/blob/main/tests/suites/stagger.test.js).

### Can stagger be used with CSS properties that require specific units?

Yes. When you pass a string containing units to `stagger()`, such as `stagger('2rem')` or `stagger('10px')`, the utility detects the unit suffix and appends it to each computed numeric value. This allows you to create staggered translations, margins, or other dimensional properties while maintaining valid CSS unit syntax.

### What is the difference between linear and grid-based staggering?

Linear staggering (the default) calculates offsets based solely on the element's index in the one-dimensional array of targets. Grid-based staggering, activated by providing `grid: [columns, rows]`, calculates Euclidean distances from the origin point within a two-dimensional matrix. Grid mode enables radial ripple effects and axis-specific cascades that respect spatial layout rather than just DOM order.

### How do I reverse the order of a staggered animation without changing the DOM?

Pass `reversed: true` in the stagger parameters. This inverts the distance map after the origin is calculated, causing the animation to flow from the last element toward the first (or from the periphery toward the center when combined with `from: 'center'`). You can also set `from: 'last'` to start the calculation from the final element while maintaining forward progression.