GSAP Cheatsheet

Callbacks

Use this GSAP reference while you build software engineering projects, review code for technical interview prep, or polish examples for a software engineer resume.

Callback Overview

Callbacks are functions called at specific lifecycle moments of a tween or timeline. They go in the vars object alongside animation properties.

CallbackWhen it fires
onStartFirst time the playhead moves past the start (once per play)
onUpdateEvery frame while active
onCompleteWhen the tween/timeline reaches its end
onRepeatAt the start of each repeat cycle
onReverseCompleteWhen playing in reverse and the playhead reaches the beginning
onInterruptWhen killed or overwritten before completing
onRefreshScrollTrigger: when scroll positions recalculate

Syntax

gsap.to(".box", {
  x: 200,
  duration: 1,

  onStart:           () => console.log("started"),
  onUpdate:          () => console.log("updating"),
  onComplete:        () => console.log("done"),
  onRepeat:          () => console.log("repeating"),
  onReverseComplete: () => console.log("reversed to start"),
  onInterrupt:       () => console.log("interrupted"),

  // Corresponding params arrays
  onStartParams:    [param1, param2],
  onUpdateParams:   [param1],
  onCompleteParams: [param1, param2],
  // etc.
});

Passing Arguments to Callbacks

gsap.to(".box", {
  x: 200,
  onComplete: handleComplete,
  onCompleteParams: ["slide", ".box", 42],
});

function handleComplete(animName, selector, value) {
  console.log(animName, selector, value);
}

"{self}" — pass the tween instance as an argument

gsap.to(".box", {
  x: 200,
  onComplete: (self) => {
    console.log("duration was:", self.duration());
    console.log("target:", self.targets()[0]);
  },
  onCompleteParams: ["{self}"],
});

"{self}" is a special string GSAP resolves to the tween/timeline instance at call time.

onStart

Fires once when playback begins (not on each repeat).

gsap.from(".hero", {
  opacity: 0,
  y: 40,
  duration: 0.8,
  onStart() {
    document.querySelector(".loader").remove();
  },
});

onUpdate

Fires every frame — useful for reading the animated value.

const obj = { value: 0 };

gsap.to(obj, {
  value: 100,
  duration: 2,
  onUpdate() {
    document.querySelector(".counter").textContent = Math.round(obj.value);
  },
});

// Access progress inside onUpdate via "this" (in non-arrow functions)
gsap.to(".box", {
  x: 300,
  duration: 1,
  onUpdate: function () {
    console.log("progress:", this.progress()); // 0 → 1
    console.log("time:", this.time());
  },
});

In arrow functions this is the outer scope. Use a regular function or capture the tween in a variable to access tween.progress().

onComplete

gsap.to(".modal", {
  autoAlpha: 0,
  y: -30,
  duration: 0.4,
  onComplete() {
    this.targets()[0].remove(); // remove element after fade-out
  },
});

// Chaining animations manually via onComplete
gsap.to(".a", {
  x: 100,
  onComplete: () => gsap.to(".b", { y: 50, duration: 0.5 }),
});

onRepeat

let count = 0;
gsap.to(".flash", {
  opacity: 0,
  repeat: -1,
  yoyo: true,
  duration: 0.5,
  onRepeat() {
    count++;
    if (count >= 6) this.kill();
  },
});

onReverseComplete

Fires when the playhead hits time 0 while playing in reverse.

const tl = gsap.timeline({ paused: true });
tl.to(".overlay", { autoAlpha: 1, duration: 0.3 })
  .from(".modal",  { y: -40, opacity: 0, duration: 0.4 });

tl.play();

closeBtn.addEventListener("click", () => {
  tl.reverse();
  tl.eventCallback("onReverseComplete", () => {
    modal.style.display = "none";
  });
});

onInterrupt

gsap.to(".box", {
  x: 400,
  duration: 2,
  onInterrupt() {
    console.log("Tween was killed before completing");
  },
});

eventCallback() — get/set callbacks after creation

const tween = gsap.to(".box", { x: 200, duration: 1 });

// Set a callback after creation
tween.eventCallback("onComplete", () => console.log("done"));
tween.eventCallback("onUpdate",   myUpdateFn, ["arg1"]);

// Get the current callback function
const fn = tween.eventCallback("onComplete");

// Remove a callback
tween.eventCallback("onComplete", null);

Timeline Callbacks

Timeline callbacks fire relative to the timeline's playhead, not individual children.

const tl = gsap.timeline({
  onStart:    () => console.log("timeline started"),
  onUpdate:   () => console.log("timeline progress:", tl.progress()),
  onComplete: () => console.log("all done"),
  onRepeat:   () => console.log("looping"),
});

tl.to(".a", { x: 100 }).to(".b", { y: 50 });

call() — callbacks at a specific point in a timeline

const tl = gsap.timeline();

tl.to(".a", { x: 200 })
  .call(showToast, ["Hello!"])          // runs when previous tween ends
  .to(".b", { y: 100 })
  .call(trackEvent, ["step2"], "+=0.2") // 0.2s after .b completes
  .call(() => console.log("done"), null, "myLabel"); // at a label

Counting Frames / Reading Tween State in Callbacks

gsap.to(".progress-bar", {
  width: "100%",
  duration: 5,
  ease: "none",
  onUpdate: function () {
    const pct = Math.round(this.progress() * 100);
    document.title = `Loading ${pct}%`;
  },
  onComplete: function () {
    document.title = "Ready";
    this.targets()[0].classList.add("complete");
  },
});

Gotchas

  • Callbacks fire in the GSAP ticker, not in a microtask queue. DOM reads inside onUpdate can trigger layout — batch carefully.
  • onComplete fires once, even with repeat: -1 — use onRepeat for per-cycle logic.
  • With yoyo: true, onComplete fires at the forward end; onReverseComplete fires at the backward end.
  • Don't mutate the targets array inside a callback while GSAP is iterating it. Schedule via gsap.delayedCall(0, fn) if needed.
  • Arrow function callbacks lose this context (the tween). Use function() or close over the tween variable.