Timeline

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

Mechanics

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.

script.js

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.

script.js

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.
When

Use it for

  • Infinite marquees and ticker strips (repeat: -1 on 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
Alternatives

Use something else when

  • You want the loop to reverse on alternate passes instead of jumping back to the start, add yoyo: true (with repeatDelay the pause then lands at each turnaround)
  • It is a truly seamless scroll loop (marquee), a raw repeat: -1 snaps at the wrap, use the wrapping timeline pattern that resets totalTime so there is no visible seam
  • The motion is a simple continuous spin or fade, plain CSS @keyframes with animation-iteration-count: infinite is lighter and needs no JS
  • You need per-cycle randomness, reach for repeatRefresh: true rather than rebuilding the tween each loop
In production

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: -1 and reverses direction on demand, so the strip runs forever until you stop it
  • Text Shimmer Wave gives each character its own repeat: -1 timeline with a computed repeatDelay, so the highlight sweeps across the word, pauses, then sweeps again on a steady cadence

Infinite loops and reduced motion

An 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.
Used in components

See it running in production

FAQ

Common questions

Does repeat: 2 play the animation twice or three times?
Three times. repeat is the number of ADDITIONAL cycles after the first play, so repeat: 2 means one initial play plus two repeats. This trips people up constantly. If you want it to play exactly twice, use repeat: 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?
delay is the wait before the FIRST play. repeatDelay is the gap before every REPEAT, and it does not apply to the initial pass. Use delay to stagger when a loop starts and repeatDelay to 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: true the animation reverses on each pass, and repeatDelay inserts 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.random call or x: "+=100") are resolved once when the tween first renders, so every repeat reuses them. Add repeatRefresh: true and GSAP re-evaluates those values at the start of each cycle.