Composables

useScrollTrigger()

Scroll-driven animations with GSAP ScrollTrigger.

Setup

Enable the plugin in nuxt.config.ts:

nuxt.config.ts
export default defineNuxtConfig({
  gsap: {
    plugins: ['ScrollTrigger'],
  },
})

Basic usage

The simplest way: pass scrollTrigger directly inside any gsap.to/from call.

components/FadeIn.vue
<script setup lang="ts">
const boxRef = ref<HTMLElement | null>(null)

onMounted(() => {
  gsap.from(boxRef.value, {
    opacity: 0,
    y: 40,
    duration: 0.8,
    scrollTrigger: boxRef.value,
  })
})
</script>

<template>
  <div ref="boxRef">Scroll to reveal me</div>
</template>

For more control over start/end positions and cleanup:

components/ScrollSection.vue
<script setup lang="ts">
const ScrollTrigger = useScrollTrigger()
const sectionRef = ref<HTMLElement | null>(null)

onMounted(() => {
  if (!sectionRef.value) return

  gsap.from(sectionRef.value, {
    opacity: 0,
    y: 60,
    duration: 1,
    scrollTrigger: {
      trigger: sectionRef.value,
      start: 'top 80%',
      end: 'top 40%',
      scrub: true,
    },
  })
})

onUnmounted(() => {
  ScrollTrigger.getAll().forEach(t => t.kill())
})
</script>

<template>
  <section ref="sectionRef">
    <h2>Scroll to reveal</h2>
  </section>
</template>

Using with gsap.context()

The context form of useGsap() automatically reverts all ScrollTrigger instances it creates:

const containerRef = ref<HTMLElement | null>(null)

useGsap(() => {
  gsap.from('.card', {
    opacity: 0,
    y: 40,
    stagger: 0.1,
    scrollTrigger: {
      trigger: '.card',
      start: 'top 85%',
    },
  })
}, { scope: containerRef })

Pinning

onMounted(() => {
  ScrollTrigger.create({
    trigger: sectionRef.value,
    pin: true,
    start: 'top top',
    end: '+=500',
  })
})

Refreshing

Call ScrollTrigger.refresh() after dynamic content changes (e.g. image load, route change):

onMounted(async () => {
  await nextTick()
  ScrollTrigger.refresh()
})
ScrollSmoother requires ScrollTrigger to also be listed in plugins.

ScrollTrigger docs

Copyright © 2026