# Understanding the Composition System in Anime.js: Managing Multiple Animations on the Same Property

> Explore Anime.js composition system to manage multiple animations. Learn how replace and blend tweens resolve conflicts on the same property for smoother animations.

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

---

**The composition system in Anime.js resolves conflicts between concurrent animations by maintaining per-target-property linked lists, where `replace` tweens override or trim overlapping predecessors while `blend` tweens sum their deltas through a shared lookup tween.**

The Anime.js library (juliangarnier/anime) implements a sophisticated composition system to handle scenarios where multiple animations target the same CSS property or attribute on a single element. Instead of simply overwriting values, the engine uses distinct **composition types**—defined in [`src/core/consts.js`](https://github.com/juliangarnier/anime/blob/main/src/core/consts.js)—to determine whether a new tween should replace existing ones or blend additively with them. This architecture ensures predictable behavior whether you are interrupting in-flight animations or layering cumulative effects.

## Composition Types and Constants

The foundation of the system rests on three composition behaviors defined in **[`src/core/consts.js`](https://github.com/juliangarnier/anime/blob/main/src/core/consts.js)** at lines 40–45:

- **`replace`** (default): New tweens overwrite or override previous tweens for overlapping time ranges.
- **`blend`** (additive): New tweens add their delta values to existing animations (e.g., `+=10` syntax).
- **`none`**: The tween runs independently without affecting or being affected by other tweens on the same property.

Each tween carries a `_composition` flag that the engine checks when inserting the animation into the render pipeline.

## Replace Composition and the Sibling Linked List

When a tween uses `compositionTypes.replace`, the system manages it through the `composeTween` function in **[`src/animation/composition.js`](https://github.com/juliangarnier/anime/blob/main/src/animation/composition.js)**.

### The Lookup Table Structure

The engine maintains two lookup tables to organize tweens:

- **`lookups._rep`**: Stores linked lists of replace-type tweens per target-property pair.
- **`lookups._add`**: Stores linked lists of additive tweens.

These maps are instantiated at lines 45–50 in [`src/animation/composition.js`](https://github.com/juliangarnier/anime/blob/main/src/animation/composition.js). The helper `getTweenSiblings` (lines 58–68) retrieves the appropriate list for a given target and property.

### Inserting and Sorting Tweens

When composing a replace tween, the engine inserts it into the sibling list using `addChild`, sorting by absolute start time via `addTweenSortMethod`:

```javascript
if (tweenCompositionType === compositionTypes.replace) {
    addChild(siblings, tween, addTweenSortMethod, '_prevRep', '_nextRep');
    // Handle overlapping previous tweens...
}

```

The linked list uses `_prevRep` and `_nextRep` pointers to maintain the sequence.

### Overriding Overlapping Animations

If a **previous tween** exists and its time range overlaps the new tween, the engine calls `overrideTween(prevSibling)` (lines 83–88) to resolve the conflict. The algorithm may trim the earlier tween's duration or completely override it, ensuring the new tween fully controls the property for its duration. For looped animations from different instances, the system specifically checks for intersections at lines 118–146 and overrides the overlapping portion to prevent conflicting values.

## Blend (Additive) Composition and Delta Accumulation

Additive animations use `compositionTypes.blend` and follow a different path in `composeTween`:

```javascript
} else if (tweenCompositionType === compositionTypes.blend) {
    const additiveTweenSiblings = getTweenSiblings(tween.target, tween.property, '_add');
    const additiveAnimation = addAdditiveAnimation(lookups._add);
    // Create lookup tween, convert TO-value to delta...
}

```

### Lookup Tweens and Base Values

The first time a property receives an additive tween, the system creates a **lookup tween** that holds the base (original) value. This lookup tween is marked with `compositionTypes.replace` internally so it behaves like a standard replace tween. The incoming additive tween then has its target value converted to a **delta** relative to this base:

```javascript
// The tween contributes only its change amount
_fromNumber = lookupTween._fromNumber - toNumber;
_toNumber = 0;

```

The tween is linked into the additive sibling list using `_prevAdd` and `_nextAdd` pointers.

### Aggregating Additive Values

Each frame, the function `addAdditiveAnimation` in **[`src/animation/additive.js`](https://github.com/juliangarnier/anime/blob/main/src/animation/additive.js)** (lines 54–78) walks every additive property list and sums the `_number` (or `_numbers` for complex values) of all active sibling tweens. It writes the total back to the lookup tween's target value (`lookupTween._toNumber = additiveValue`), then forces a render of the temporary additive animation via `render(animation, 1, 1, 0, tickModes.FORCE)`.

This design allows multiple `+=` animations to run simultaneously, with their combined deltas applied to the element's base value.

## Removing Tweens and Cleanup

When a tween is cancelled or completes, `removeTweenSliblings` (lines 68–99 in [`src/animation/composition.js`](https://github.com/juliangarnier/anime/blob/main/src/animation/composition.js)) cleans the appropriate sibling list. For additive tweens, if the removed tween was the last child, the function also removes the lookup tween and deletes the map entry to prevent memory leaks.

## Summary

- **Composition types** (`replace`, `blend`, `none`) are defined in [`src/core/consts.js`](https://github.com/juliangarnier/anime/blob/main/src/core/consts.js) and determine how concurrent animations interact.
- **Replace tweens** are stored in `lookups._rep` linked lists; overlapping tweens are overridden or trimmed by `overrideTween` to ensure the latest animation takes precedence.
- **Blend tweens** are stored in `lookups._add` and use a hidden lookup tween to hold base values; deltas are summed each frame in [`src/animation/additive.js`](https://github.com/juliangarnier/anime/blob/main/src/animation/additive.js).
- **Linked lists** use `_prevRep`/`_nextRep` for replace tweens and `_prevAdd`/`_nextAdd` for additive tweens to maintain sort order.
- **Cleanup** is handled by `removeTweenSliblings`, which purges empty lists and lookup tweens when animations end.

## Frequently Asked Questions

### What happens when two animations target the same property in Anime.js?

When two animations target the same property, the composition system in Anime.js checks the `_composition` flag of the new tween. If both use the default `replace` type, the later tween overrides the earlier one for any overlapping time range, potentially trimming the first tween's duration via `overrideTween`. If both use `blend`, their delta values are summed each frame and applied to a shared lookup tween, creating a cumulative effect.

### How do I create additive animations in Anime.js?

To create additive animations, use the `blend` composition type (often triggered by relative values like `+=10` or `-=20`). The engine automatically creates a lookup tween to store the base value, converts your target value to a delta, and links the tween into the additive sibling list (`lookups._add`). Each frame, `addAdditiveAnimation` aggregates all active deltas and renders the combined result.

### What is the difference between replace and blend composition in Anime.js?

**Replace** composition (the default) means a new tween takes full control of the property, overriding or trimming any overlapping tweens so only the latest value applies. **Blend** composition means the tween adds its change to existing values; the engine sums all active additive deltas and applies the total to the element's base value, allowing simultaneous animations to contribute to the final result.

### Where does the composition logic live in the Anime.js source code?

The core composition logic resides in three key files: [`src/core/consts.js`](https://github.com/juliangarnier/anime/blob/main/src/core/consts.js) defines the composition type constants; [`src/animation/composition.js`](https://github.com/juliangarnier/anime/blob/main/src/animation/composition.js) implements `composeTween`, `getTweenSiblings`, and `overrideTween` for managing sibling linked lists; and [`src/animation/additive.js`](https://github.com/juliangarnier/anime/blob/main/src/animation/additive.js) handles the frame-by-frame aggregation of additive values via `addAdditiveAnimation`.