repeat & repeatDelay
repeat and repeatDelay are GSAP special properties that loop a tween or timeline a set number of times, with an optional gap between each pass. `repeat` is how many EXTRA times it plays after the first (so `repeat: 2` plays three times total, and `repeat: -1` loops forever), and `repeatDelay` is the pause in seconds inserted before each repeat.
Updated July 1, 2026
How repeat and repeatDelay work
repeat counts ADDITIONAL cycles, not total plays. repeat: 0 (the default) plays once, repeat: 1 plays twice, repeat: 2 plays three times. Passing repeat: -1 is the special case that loops infinitely, which sets the animation's total duration to Infinity.
repeatDelay is the gap in seconds before EACH repeat. It does not apply before the first play, that is what delay is for. So a 1s tween with repeat: -1 and repeatDelay: 0.5 plays for 1s, waits 0.5s, plays again, waits 0.5s, and so on.
Both properties work identically on a tween and on a whole timeline. On a timeline they loop the entire sequence, which is the usual way to build a repeating multi-step animation instead of setting repeat on every child.
Two properties that pair with repeat
onRepeat fires a callback at the start of each new cycle, useful for swapping content or counting passes. repeatRefresh: true re-reads function-based and relative values (like x: "+=100" or a random from gsap.utils.random) on every iteration, so each loop can land on fresh values instead of the ones baked in at build time.Use it for
- Infinite marquees and ticker strips (
repeat: -1on the scroll timeline) - Ambient looping motion (pulsing dots, breathing scale, shimmer sweeps)
- Attention loops that pause between passes (a nudge that plays, waits a beat, plays again via
repeatDelay) - Looping loaders and progress spinners that run until a task finishes, then get
.kill()ed - Any repeating sequence where you want the whole timeline to cycle, not each tween individually
Use something else when
- You want the loop to reverse on alternate passes instead of jumping back to the start, add
yoyo: true(withrepeatDelaythe pause then lands at each turnaround) - It is a truly seamless scroll loop (marquee), a raw
repeat: -1snaps at the wrap, use the wrapping timeline pattern that resetstotalTimeso there is no visible seam - The motion is a simple continuous spin or fade, plain CSS
@keyframeswithanimation-iteration-count: infiniteis lighter and needs no JS - You need per-cycle randomness, reach for
repeatRefresh: truerather than rebuilding the tween each loop
Used in these Annnimate components
Looping is the whole job for a few Annnimate components, and they lean on both properties directly:
- Marquee builds a single scroll timeline with
repeat: -1and reverses direction on demand, so the strip runs forever until you stop it - Text Shimmer Wave gives each character its own
repeat: -1timeline with a computedrepeatDelay, so the highlight sweeps across the word, pauses, then sweeps again on a steady cadence
Infinite loops and reduced motion
repeat: -1 animation is exactly the kind of constant motion users with vestibular sensitivity want gone, and prefers-reduced-motion adoption jumped from 34% of sites in 2022 to over 50% of mobile sites in 2024 (HTTP Archive Web Almanac, Accessibility). Gate any infinite loop behind gsap.matchMedia() so a reduced-motion query kills it or drops the duration to 0.See it running in production
Common questions
- Does repeat: 2 play the animation twice or three times?
- Three times.
repeatis the number of ADDITIONAL cycles after the first play, sorepeat: 2means one initial play plus two repeats. This trips people up constantly. If you want it to play exactly twice, userepeat: 1. - How do I make a GSAP animation loop forever?
- Set
repeat: -1. This is the special value for infinite repeats and sets the animation's total duration to Infinity. Store the return value so you can.kill()or.pause()it later, since an infinite tween never completes on its own. - What is the difference between delay and repeatDelay?
delayis the wait before the FIRST play.repeatDelayis the gap before every REPEAT, and it does not apply to the initial pass. Usedelayto stagger when a loop starts andrepeatDelayto control the rhythm between its cycles. You can set both on the same animation.- Does repeatDelay add a pause at both ends when I use yoyo?
- Yes. With
yoyo: truethe animation reverses on each pass, andrepeatDelayinserts the pause at each turnaround, so you get play, pause, play-in-reverse, pause, and so on. That is the standard way to build a gentle back-and-forth with a hold at each extreme. - Why does my repeating tween not pick up new random values each loop?
- Function-based and relative values (like a
gsap.utils.randomcall orx: "+=100") are resolved once when the tween first renders, so every repeat reuses them. AddrepeatRefresh: trueand GSAP re-evaluates those values at the start of each cycle.
.to() / .from() / .set() call.NextSeamless loopA seamless loop is a GSAP animation set to repeat: -1 whose end state matches its start state exactly, so it plays forever with no visible jump at the loop point.