Skip to content

Anime.js Timeline — Complete Guide with Examples

DodaTech Updated 2026-06-28 5 min read

In this tutorial, you'll learn about the Anime.js timeline. We cover key concepts, practical examples, and best practices to help you understand and apply this topic effectively.

The Anime.js timeline lets you sequence multiple animations with precise timing control, adding them in order with relative delays, offsets, and synchronization for complex animation chains.

What You'll Learn

By the end of this tutorial, you'll create timelines with sequenced animations, use relative and absolute offsets, stagger children, loop entire timelines, and control timeline playback.

Why It Matters

Individual animations are simple. Real-world animations need Orchestration: a modal slides in, then the content fades in, then a success icon bounces. Timelines handle this orchestration with clean, readable code instead of nested callbacks.

Real-World Use

Doda Browser uses Anime.js timelines for its onboarding tutorial. Each step slides in, pauses for the user to read, then the next step slides in. The timeline ensures perfect sequencing without timing guesswork.

Where This Fits in Your Learning Path

flowchart LR
    A["Animation Parameters"] --> B["**Timeline & Controls**"]
    B --> C["Easing & Callbacks"]
    C --> D["SVG & Morph"]
    D --> E["Advanced Anime.js"]
    style B fill:#f97316,stroke:#c2410c,color:#fff
    style A fill:#e5e7eb,stroke:#9ca3af,color:#374151
    style E fill:#22c55e,stroke:#16a34a,color:#fff

Creating a Timeline

A timeline is created with anime.timeline() and animations are added with .add().

const tl = anime.timeline({
  easing: 'easeOutExpo',
  duration: 1000
})

tl.add({
  targets: '.box',
  translateX: 200
}).add({
  targets: '.box',
  rotate: '1turn'
}).add({
  targets: '.box',
  translateY: 100
})

Expected output: The box moves right 200px, then rotates 360 degrees, then moves down 100px. Each step takes 1 second.

Relative Offsets

Use numbers or strings with + and -= to offset animations relative to the previous one.

const tl = anime.timeline({ duration: 800 })

tl.add({
  targets: '.circle',
  translateX: 150
}).add({
  targets: '.circle',
  scale: 1.5
}, 200)  // starts 200ms after previous ends

tl.add({
  targets: '.circle',
  rotate: '1turn'
}, '-=400')  // starts 400ms before previous ends (overlap)

Expected output: The circle moves, then waits 200ms, then scales. The rotation overlaps with the last 400ms of the scaling.

Absolute Time Offsets

Use offset (not relative) to place animations at exact timeline positions in milliseconds.

const tl = anime.timeline({ duration: 500 })

tl.add({ targets: '.a', translateX: 100 }, 0)     // starts immediately
tl.add({ targets: '.b', translateX: 100 }, 500)   // starts at 500ms
tl.add({ targets: '.c', translateX: 100 }, 1000)  // starts at 1000ms

Expected output: Elements A, B, and C animate in sequence with no gaps between them.

Looping a Timeline

Set loop on the timeline to repeat the entire sequence.

const tl = anime.timeline({
  loop: true,
  direction: 'alternate',
  duration: 600
})

tl.add({ targets: '.box', translateY: -80 })
tl.add({ targets: '.box', scale: 0.8 })
tl.add({ targets: '.box', backgroundColor: '#ff6b6b' })

Expected output: The box jumps up, shrinks, and changes color, then reverses through the sequence back to the start.

Timeline Playback Controls

Timelines support the same controls as individual animations.

const tl = anime.timeline({ autoplay: false, duration: 1000 })

tl.add({ targets: '.box', translateX: 100 })
tl.add({ targets: '.box', rotate: '1turn' })
tl.add({ targets: '.box', translateX: 0 })

document.querySelector('#playBtn').addEventListener('click', () => tl.play())
document.querySelector('#pauseBtn').addEventListener('click', () => tl.pause())
document.querySelector('#reverseBtn').addEventListener('click', () => tl.reverse())

Expected output: Play starts the timeline from the beginning. Pause stops it. Reverse flips direction.

Common Mistakes

1. Forgetting .add() returns the timeline

tl.add() returns the timeline, enabling chaining. Forgetting to return or chain causes errors.

2. Using absolute offsets that overlap incorrectly

Overlapping animations on the same property of the same element override each other. Use multiple elements or different properties.

3. Setting duration on individual .add() calls

Duration can be set on the timeline (applies to all) or on individual .add() calls (overrides). Mixing them causes confusion.

4. Expecting timeline.complete to fire for each sub-animation

complete fires once when the entire timeline finishes, not after each .add() segment.

5. Creating circular timeline dependencies

Avoid adding animations that depend on timeline state within the same timeline. This creates circular logic that breaks sequencing.

Practice Questions

  1. How do you create a timeline? const tl = anime.timeline() and then tl.add({ ... }).

  2. What does offset: 500 do in a timeline? It places the animation at exactly 500ms on the timeline, regardless of previous animations.

  3. Can you loop a timeline? Yes. Set loop: true when creating the timeline or later with tl.loop = true.

  4. How do you overlap animations in a timeline? Use negative string offsets like '-=300' to start before the previous animation ends.

  5. Do timeline animations run sequentially by default? Yes. Each .add() waits for the previous to complete before starting.

Challenge

Build an onboarding flow with 4 steps. Each step slides in from the right, the content fades in, and after 2 seconds the next step begins. Loop the entire sequence after the last step.

FAQ

Can I nest timelines?

No. Timelines cannot be nested directly. Use the .add() method on a single timeline to sequence all animations.

What happens if I add an animation to a finished timeline?

The animation is added but will only play if the timeline is reset or reversed back to that point.

Can timeline children have different easings?

Yes. Each .add() call can specify its own easing, overriding the timeline default.

How do I seek to a specific point in a timeline?

Use tl.seek(timeInMs) to jump to any position in the timeline.

Does a timeline respect the complete callback of child animations?

No. Child animation callbacks fire but the timeline's complete callback fires once when all children finish.


Mini Project

Build a product showcase animation. Three product cards animate in sequence: the first slides in from the left, the second fades and scales up from the center, and the third slides in from the right. After all three, a banner bounces in at the bottom.

const tl = anime.timeline({
  easing: 'easeOutExpo',
  duration: 800
})

tl.add({
  targets: '.card-1',
  translateX: [-200, 0],
  opacity: [0, 1]
}).add({
  targets: '.card-2',
  scale: [0, 1],
  opacity: [0, 1]
}, 200).add({
  targets: '.card-3',
  translateX: [200, 0],
  opacity: [0, 1]
}, 200).add({
  targets: '.banner',
  translateY: [100, 0],
  opacity: [0, 1],
  easing: 'easeOutBounce'
}, 400)
<div class="card-1" style="display:inline-block;width:100px;height:150px;background:#ff6b6b;border-radius:8px;opacity:0"></div>
<div class="card-2" style="display:inline-block;width:100px;height:150px;background:#4ecdc4;border-radius:8px;opacity:0"></div>
<div class="card-3" style="display:inline-block;width:100px;height:150px;background:#ffe66d;border-radius:8px;opacity:0"></div>
<div class="banner" style="width:100%;height:40px;background:#a29bfe;border-radius:4px;margin-top:20px;opacity:0;text-align:center;color:white;line-height:40px">Special Offer!</div>

What's Next

Deepen your easing and callback knowledge:

Tutorial What You'll Learn
Easing and Callbacks Custom easing curves and animation event callbacks
SVG and Motion Paths Animating SVG elements along paths

Related topics: JavaScript timing and sequencing, callback patterns.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro