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