# How to Compose Multiple Animations on the Same Elements in Anime.js

> Master composing multiple animations on the same elements in Anime.js. Learn replace blend and none modes to control how animations interact for complex visual effects.

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

---

**Anime.js enables multiple tweens on the same element through three composition modes—`replace` (default), `blend`, and `none`—which determine whether animations override, add to, or ignore each other.**

When building complex web animations, you often need to layer effects on a single element or property. The `anime` library (juliangarnier/anime) handles these overlapping timelines through a sophisticated **animation composition** system defined in [`src/core/consts.js`](https://github.com/juliangarnier/anime/blob/main/src/core/consts.js). Understanding how to compose multiple animations allows you to create sophisticated interactions where motion effects mix additively or sequentially replace one another.

## Understanding Animation Composition Types

Anime.js defines composition behavior in [`src/core/consts.js`](https://github.com/juliangarnier/anime/blob/main/src/core/consts.js) (lines 41–45) through three distinct modes:

- **`replace`** (0): The default mode. New tweens override overlapping tweens on the same target and property. The previous animation is trimmed or cancelled so only one value applies at any given time.
- **`blend`** (2): New tweens add their delta to the current value using additive blending. All active tweens contribute to the final computed value.
- **`none`** (1): No composition handling. Tweens run independently, used internally for performance optimization on massive target sets.

The default `replace` mode matches the most common use case: later animations override earlier ones for the overlapped time range.

## How Composition Works Internally

The composition system relies on three core modules that manage tween registration, storage, and rendering.

### Tween Registration and Sibling Lists

When you create an animation, the `composeTween` function in [`src/animation/composition.js`](https://github.com/juliangarnier/anime/blob/main/src/animation/composition.js) determines how the new tween interacts with existing ones. The system maintains **lookup maps** (`lookups._rep` for replace mode, `lookups._add` for blend mode) that store doubly-linked lists of sibling tweens per target/property.

The `getTweenSiblings(target, property, lookup)` function returns an object with `_head` and `_tail` pointers representing the chain of tweens affecting the same property. This structure enables **O(1)** insertion and removal without scanning every tween in the scene.

For `replace` mode, `addChild` inserts the tween sorted by start time using `_prevRep` and `_nextRep` pointers. When overlaps occur, `overrideTween` trims or cancels conflicting siblings. For `blend` mode, the system creates a *lookup tween* representing the accumulated base value and links additive tweens using `_prevAdd` and `_nextAdd` pointers.

### Tween Creation and Storage

In [`src/animation/animation.js`](https://github.com/juliangarnier/anime/blob/main/src/animation/animation.js) (lines 260–263 and 551–564), the library normalizes the `composition` option supplied by users and stores it on the tween instance as `_composition`. This flag determines which logic path the engine uses during the render loop.

### The Render Loop

The rendering engine in [`src/core/render.js`](https://github.com/juliangarnier/anime/blob/main/src/core/render.js) reads the `_composition` flag to determine value calculation. At lines 158–166, the engine detects the composition type, and at lines 231–236, it handles the special summation logic for `blend` mode. For `replace`, it uses the latest tween's computed value directly. For `blend`, it sums the contributions of every active tween (`tween._fromNumber`, `tween._toNumber`, etc.) before applying the final value to the DOM element.

This architecture ensures **O(k)** rendering cost, where *k* represents the number of active tweens on a specific property—typically a very low number in practice.

## Practical Examples of Animation Composition

### Replace Mode: Sequential Overrides

By default, Anime.js uses `replace` composition, allowing later animations to take precedence:

```javascript
// First animation moves element 0→200px over 2s
anime({
  targets: '.box',
  translateX: 200,
  duration: 2000
});

// Second animation starts at 1s, overriding translateX
anime({
  targets: '.box',
  translateX: 0,
  duration: 2000,
  delay: 1000
});

```

From 0–1 seconds, the box moves toward 200px. At the 1-second mark, the second tween takes over, bringing the element back to 0px while the first tween remains alive in the timeline but no longer controls the property.

### Blend Mode: Additive Animations

To combine motion effects, use `composition: 'blend'`:

```javascript
// Base tween adds 100px to translateX
anime({
  targets: '.ball',
  translateX: 100,
  duration: 3000,
  composition: 'blend'
});

// Independent tween adds another 50px
anime({
  targets: '.ball',
  translateX: 50,
  duration: 2000,
  delay: 500,
  composition: 'blend'
});

```

The ball ends up at 150px because both deltas sum together. If the second animation ends earlier, the ball continues at 100px from the remaining active tween. Both animations must specify `blend` mode to participate in additive composition.

### Mixed Composition Strategies

You can apply different composition modes to different properties on the same element:

```javascript
anime({
  targets: '.star',
  rotate: '1turn',
  duration: 4000
});

anime({
  targets: '.star',
  scale: 2,
  duration: 4000,
  composition: 'blend',
  delay: 1000
});

anime({
  targets: '.star',
  scale: 0.5,
  duration: 2000,
  composition: 'blend',
  delay: 2000
});

```

Here, rotation follows `replace` semantics (default), while the two scale animations combine multiplicatively (2 × 0.5 = 1). The star completes one full rotation while scaling up then down to its original size.

## Performance Considerations

The composition system in juliangarnier/anime is optimized for real-time performance. By maintaining doubly-linked lists per property via `lookups._rep` and `lookups._add` in [`src/animation/composition.js`](https://github.com/juliangarnier/anime/blob/main/src/animation/composition.js), the engine achieves constant-time insertion and removal. During the render loop in [`src/core/render.js`](https://github.com/juliangarnier/anime/blob/main/src/core/render.js), the engine only processes active tweens for specific properties, keeping the per-frame cost proportional to the number of conflicting animations rather than the total tween count.

## Summary

- **Composition modes** (`replace`, `blend`, `none`) in [`src/core/consts.js`](https://github.com/juliangarnier/anime/blob/main/src/core/consts.js) control how multiple animations interact on the same element.
- **`replace`** (default) overrides overlapping values, while **`blend`** sums deltas additively.
- The **sibling list architecture** in [`src/animation/composition.js`](https://github.com/juliangarnier/anime/blob/main/src/animation/composition.js) uses `_prevRep`, `_nextRep`, `_prevAdd`, and `_nextAdd` pointers for efficient tween management.
- **Rendering logic** in [`src/core/render.js`](https://github.com/juliangarnier/anime/blob/main/src/core/render.js) (lines 158–166 and 231–236) determines final values based on the `_composition` flag stored during tween creation in [`src/animation/animation.js`](https://github.com/juliangarnier/anime/blob/main/src/animation/animation.js).
- **Additive animations** require all participating tweens to specify `composition: 'blend'`.

## Frequently Asked Questions

### What happens when two animations target the same property without specifying composition?

By default, Anime.js applies `replace` composition. The second animation overrides the first during their overlap period. According to the source code in [`src/animation/animation.js`](https://github.com/juliangarnier/anime/blob/main/src/animation/animation.js) (lines 260–263), the library automatically defaults to `replace` mode when no composition is specified.

### Can I mix replace and blend modes on different properties of the same element?

Yes. The composition mode is evaluated per property, not per element. You can animate `translateX` with `replace` while animating `scale` with `blend` on the same target. The lookup maps in [`src/animation/composition.js`](https://github.com/juliangarnier/anime/blob/main/src/animation/composition.js) maintain separate sibling lists for each property.

### How does blend mode calculate the final value?

During each frame, the render loop in [`src/core/render.js`](https://github.com/juliangarnier/anime/blob/main/src/core/render.js) (lines 231–236) iterates through all active tweens in the additive list and sums their individual contributions (`_fromNumber`, `_toNumber` interpolated by progress) before applying the result to the DOM element. This creates true additive animation where multiple motion vectors combine.

### Is there a performance penalty for using blend mode?

No significant penalty exists for typical use cases. The system maintains **O(1)** insertion/removal and **O(k)** rendering costs, where *k* is the small number of active tweens on a specific property. The `none` composition type exists in [`src/core/consts.js`](https://github.com/juliangarnier/anime/blob/main/src/core/consts.js) specifically for edge cases involving massive target sets where even minimal composition overhead should be avoided.