Timeline

Timeline labels

Timeline labels are named time positions you attach to a GSAP timeline with `addLabel()`, then reference by name to place tweens, seek the playhead, or start playback. They turn a timeline's raw seconds into readable anchors, so you sequence against `"reveal"` instead of hardcoding `1.4`.

Updated July 1, 2026

Mechanics

How timeline labels work

A label is just a name pinned to a time on the timeline. addLabel(name, position) records it, and from then on you can pass that name anywhere GSAP expects a position: the third argument of a tween, a seek() target, or a play() start point. If you omit the position, the label lands at the current end of the timeline.

script.js

Because the subhead and CTA are placed relative to "reveal", retiming the hero tween shifts everything downstream automatically. You never touch the numbers below the label. That is the whole point: the label is the single source of truth for a moment in the sequence.

Seeking and playing by name

Labels double as jump targets. seek() moves the playhead without playing, play() resumes from a label, and tweenTo() / tweenFromTo() animate the playhead between two labels with their own duration and ease.

script.js

Passing a string as the position adds a label too

tl.add("loopStart", 3.2) is shorthand for addLabel("loopStart", 3.2). GSAP's horizontalLoop helper leans on this to drop a label at the exact time each item reaches the start of the strip, so it can later tweenTo any item by name.
When

Use timeline labels for

  • Sequences you retime often - anchor downstream tweens to "reveal" so shifting one beat cascades the rest
  • Named jump targets - seek("outro") or play("step2") for menus, wizards, and multi-state UI
  • Looping strips where you need to scroll to a specific item by index (tweenTo("label3"))
  • Coordinating several tweens to share one start moment - place them all at the same label
  • Self-documenting timelines - "menuOpen" reads better than the raw number 0.85 in a 40-line sequence
Alternatives

Use something else when

  • The sequence is two or three appended tweens - the default end-to-end chaining is already clear, labels add noise
  • You only need 'same start as the previous tween' - the "<" position keyword does that without naming anything
  • You want a fixed offset from the previous tween - "+=0.3" / "-=0.2" is enough, no label required
  • You need the playhead to stop mid-timeline and wait - that is addPause(position, callback), a different tool than a label
In production

Used in these Annnimate components

Labels are core GSAP, not a plugin, and GSAP runs on roughly 2.2% of all websites (w3techs, June 2026) where timelines are the standard way to choreograph multi-step motion. Two Annnimate components sit on opposite ends of the label spectrum:

  • The Marquee uses labels directly - it drops a named label at the timeline time each item reaches the start of the strip, then calls tweenTo(label) to glide the loop to any specific item on demand
  • The Multi Flip builds a paused Flip timeline and places every card's tween at a computed numeric position (index * stagger). It uses raw position parameters rather than names, which is exactly the case a label would make readable if the sequence grew a second coordinated beat

Labels do not move existing tweens

addLabel("reveal") only records a time. It never reflows tweens you already placed. If you add a label after building the timeline expecting earlier tweens to snap to it, nothing happens - place the tweens against the label as you build, not after.
Used in components

See it running in production

FAQ

Common questions

What's the difference between a label and the position parameter?
The position parameter is the argument that decides WHERE a tween goes on the timeline - it accepts an absolute time (1.2), a relative offset ("+=0.5"), a keyword ("<", ">"), or a label name. A label is one of the things you can pass as that position. So labels don't replace the position parameter, they give it human-readable names to point at.
Does addLabel move or delay my tweens?
No. A label is a passive marker - it just stores a name and a time in tl.labels. Adding one never reflows existing tweens. To make a tween sit at a label, you have to pass the label name as that tween's position parameter when you add it (tl.to('.x', {...}, 'reveal')).
How do I start playback from a specific label?
tl.play("labelName") jumps to the label and plays forward. tl.seek("labelName") moves the playhead there without playing. tl.tweenTo("labelName") and tl.tweenFromTo("a", "b") animate the playhead to or between labels with their own duration and ease, which is how looping strips scroll smoothly to a chosen item.
What happens if I call addLabel without a position?
The label lands at the current end of the timeline - whatever time the last-added tween finishes. That's why the common pattern is to build a few tweens, then addLabel("reveal") to mark 'everything before this is the intro', then keep adding tweens relative to that label.
Can I place a tween slightly after a label?
Yes. Labels take relative offsets like any position: "reveal+=0.15" starts 0.15s after the label, "reveal-=0.1" starts 0.1s before it. This is the cleanest way to fan a few elements out from one shared moment without recomputing absolute times.