Anime.js Timeline — Complete Guide with Examples
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
How do you create a timeline? const tl = anime.timeline() and then tl.add({ ... }).
What does offset: 500 do in a timeline? It places the animation at exactly 500ms on the timeline, regardless of previous animations.
Can you loop a timeline? Yes. Set loop: true when creating the timeline or later with tl.loop = true.
How do you overlap animations in a timeline? Use negative string offsets like '-=300' to start before the previous animation ends.
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
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