All Posts
·6 min read

Building Awwwards-Level Animations with GSAP and Next.js

A deep dive into creating buttery-smooth, award-winning animations using GSAP ScrollTrigger and the Next.js App Router.

Building Awwwards-Level Animations with GSAP and Next.js

When building portfolio sites or creative web experiences, animation quality is what separates good from exceptional. In this post, I'll share the patterns I use to build scroll-driven animations that feel truly premium.

Setting Up GSAP with Next.js App Router

The key to GSAP in React is the useGSAP hook from @gsap/react. It handles cleanup automatically, preventing memory leaks when components unmount.

import { useGSAP } from "@gsap/react";
import { gsap } from "gsap";
import { ScrollTrigger } from "gsap/ScrollTrigger";

gsap.registerPlugin(ScrollTrigger);

export function AnimatedSection() {
  const containerRef = useRef<HTMLDivElement>(null);

  useGSAP(() => {
    gsap.from(".fade-item", {
      opacity: 0,
      y: 80,
      stagger: 0.08,
      ease: "expo.out",
      duration: 1.2,
      scrollTrigger: {
        trigger: containerRef.current,
        start: "top 85%",
      },
    });
  }, { scope: containerRef });

  return <div ref={containerRef}>...</div>;
}

The Hydration Problem

GSAP and server-side rendering don't always play nicely. The solution is to set initial animation states in CSS and animate TO the final state in GSAP — never use gsap.from() with values that conflict with SSR-rendered markup.

This is the single most impactful technique for eliminating the "flash of unstyled content" that plagues GSAP animations in Next.js apps.

WA
wardalbam.nl