GSAP Cheatsheet
Callbacks
Use this GSAP reference while you build software engineering projects, review code, or refresh the syntax you reach for most.
Callback Overview
Callbacks are functions called at specific lifecycle moments of a tween or timeline. They go in the vars object alongside animation properties.
| Callback | When it fires |
|---|---|
onStart | First time the playhead moves past the start (once per play) |
onUpdate | Every frame while active |
onComplete | When the tween/timeline reaches its end |
onRepeat | At the start of each repeat cycle |
onReverseComplete | When playing in reverse and the playhead reaches the beginning |
onInterrupt | When killed or overwritten before completing |
onRefresh | ScrollTrigger: 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
thisis the outer scope. Use a regularfunctionor capture the tween in a variable to accesstween.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
onUpdatecan trigger layout — batch carefully. onCompletefires once, even withrepeat: -1— useonRepeatfor per-cycle logic.- With
yoyo: true,onCompletefires at the forward end;onReverseCompletefires 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
thiscontext (the tween). Usefunction()or close over the tween variable.