stagger
Stagger is a GSAP property that offsets the start time of each target in a tween, animating them one after another instead of all at once. It's the single most-used tool for making a list, grid, or sequence of elements feel choreographed rather than mechanical.
Updated June 1, 2026
How stagger works
The simplest form is a number - the delay in seconds between each target's start time:
For 10 items at stagger: 0.08, the first item starts at t=0, the last at t=0.72, and the whole sequence finishes at t=0.72 + 0.6 = 1.32s.
The richer config
The two eases compose: ease: "expo.out" is the per-element animation curve, stagger.ease is how the START TIMES distribute across the set. A power2.in stagger ease makes early items cluster close together and later items spread out - useful for 'spilling outward' effects.
Use stagger for
- Reveal animations on lists, cards, or grids
- Character-by-character text reveals (paired with SplitText)
- Grid-of-tiles entrance animations
- Sequencing logo paths or SVG elements
- Anywhere 'one after another' reads better than 'all at once'
Use something else when
- Single elements - just don't pass stagger
- True asynchronous sequencing - use a GSAP timeline with explicit position parameters per tween
- Physics-based delays - stagger is deterministic; for true randomness use
from: "random"or compute delays per-target
Used in these Annnimate components
- Dual Scramble staggers characters by 30ms with
from: "start"for a left-to-right read - The Magnetic Button uses stagger internally on its label characters when scrambling
See it running in production
Common questions
- What's the difference between stagger.each and stagger.amount?
eachis the delay between each target's start (in seconds).amountis the total time the staggered set should span - GSAP calculateseachautomatically asamount / count. Useeachwhen you want a fixed rhythm regardless of count; useamountwhen you want the total animation length to stay constant as the count changes.- How do stagger.from values like 'start', 'center', 'edges' work?
- They define WHICH target gets index 0 - the one that starts first.
start(default): first child first.end: last child first.center: middle child first, rippling outward.edges: first and last simultaneously, rippling inward.random: shuffled order. For grids, you also havefrom: [0.5, 0.5]which uses normalized 2D coordinates to pick a focal point. - Why isn't my grid stagger respecting the rows/columns?
- You need to pass
stagger: { grid: [rows, cols], ... }. Withoutgrid, GSAP treats the targets as a 1D list and staggers in DOM order. Withgrid: [3, 4], GSAP knows the layout and can stagger by distance from a focal point (from: 'center') instead of by index. - Can I combine stagger with a position parameter on a timeline?
- Yes. The position parameter (
'<','>','+=0.5') decides WHEN the staggered batch starts; the stagger itself controls the rhythm within. Common pattern:tl.to(items, { ... stagger: 0.05 }, 'reveal')to fire all staggered items together with another tween labeled 'reveal'.
repeat: -1 whose end state matches its start state exactly, so it plays forever with no visible jump at the loop point.NextTimeline controlsTimeline controls are the methods GSAP exposes on a timeline instance to drive its playhead after it's built: play(), pause(), reverse(), restart(), seek(), progress(), time(), and timeScale().