GSAP in Vue
GSAP in Vue is the pattern for driving GSAP animations from a Vue 3 component: you create your tweens inside `onMounted` once the DOM exists, scope them to the component with a template ref, and kill them in `onUnmounted`. GSAP is framework-agnostic, so there's no Vue-specific build, you're just wiring the animation into Vue's lifecycle so it starts and cleans up at the right time.
Updated July 1, 2026
How GSAP runs inside a Vue component
There is no official Vue hook the way useGSAP exists for React. Vue's onMounted / onUnmounted lifecycle already gives you the two moments you need: run the animation after the element is in the DOM, and tear it down when the component leaves. Register any plugins once at the app level (in main.js), not inside the component.
Reach for a template ref instead of a global selector string. A ref points at the exact node this instance rendered, so two copies of the same component on one page never animate each other's elements.
When you're animating several children with one selector, wrap the work in gsap.context(callback, scope) and pass the container ref as the scope. Every tween and ScrollTrigger created inside the callback is tracked, so a single ctx.revert() in onUnmounted kills them all and restores inline styles.
Vue's #2 spot is real
Use this pattern for
- Entrance reveals on a component that mounts (
onMounted+ a template ref) - Staggered lists or grids where one selector targets many children (
gsap.contextscope) - ScrollTrigger-driven sections inside a Vue or Nuxt page, created and reverted in the same context
- Hover microinteractions wired to
@mouseenter/@mouseleavehandlers that callgsap.toon a ref
Do it differently when
- You're in React, not Vue, use the
useGSAPhook from@gsap/reactwhich handles the mount and cleanup for you - The animation is a simple one-shot on a single element, a bare
gsap.from(ref.value, ...)with atween.kill()inonUnmountedis lighter than pulling ingsap.context - Content loads async and shifts layout, call
ScrollTrigger.refresh()afternextTick()so triggers recompute against the settled DOM - You need the value inside Vue reactivity (an animated counter bound to the template), animate a reactive object's property and read it in the template instead of touching the DOM node
Used in these Annnimate components
Every Annnimate component ships a Vue build alongside the React and vanilla versions, and they all follow this shape: onMounted to build, template refs instead of selectors, onUnmounted to revert.
- Text Reveal builds its line-by-line reveal timeline in
onMountedand kills it inonUnmounted, scoped to the component root so multiple headings on a page stay independent - Magnetic Button wires
gsap.quickTofollow tweens to the button ref inside the component's lifecycle, and reverts the context when the button unmounts so no pointer handler keeps firing on a detached node
See it running in production
Common questions
- Is there a useGSAP hook for Vue?
- No.
useGSAPships in the@gsap/reactpackage and is React-only. In Vue you use the framework's own lifecycle:onMountedto create the animation andonUnmountedto revert it.gsap.context()gives you the scoping and batch-cleanup thatuseGSAPwraps up in React. - Should I use a template ref or a selector string in Vue?
- Prefer a template ref for a single element, it points at exactly the node this instance rendered so two copies of the component never cross-animate. When one selector needs to hit many children (a staggered list), use
gsap.context(callback, containerRef)so the selector is scoped to that container rather than the whole page. - Where do I register ScrollTrigger in a Vue app?
- Once, at the app level, usually in
main.js:import { ScrollTrigger } from 'gsap/ScrollTrigger'thengsap.registerPlugin(ScrollTrigger). Registering inside a component's setup runs on every render and is wasteful. In Nuxt, register in a client-only plugin so it never runs during SSR. - Why does my Vue animation run before the element exists?
- You're creating the tween in
setupor at the top of<script setup>, which runs before the DOM is mounted, so the ref is still null. Move thegsapcall insideonMounted, and guard withif (!container.value) returnbefore you touch it. - How do I clean up GSAP when a Vue component unmounts?
- Call
ctx.revert()inonUnmountedif you usedgsap.context, ortween.kill()for a single tween.revert()kills every tween and ScrollTrigger created in that context and restores the inline styles GSAP set. Skipping this leaks ScrollTriggers and can leave handlers firing on detached nodes.
