Building a GSAP Footer Reveal Animation in React with AI

If you frequent Awwwards or premium agency portfolios, you've almost certainly seen the "Footer Reveal" effect. Instead of the footer scrolling into view like a normal block element, it appears to be fixed behind the page — and the main content peels away like a curtain to expose it.
It's one of the cleanest premium web interactions in existence. It signals to the visitor: this site was built with care. And critically, it keeps the footer visually present without it cluttering the main browsing experience.
The problem is, building it manually is genuinely painful. You're dealing with z-index stacking contexts that fight each other, dynamic margin calculations that break on mobile, and GSAP's ScrollTrigger plugin which has its own quirks. In this guide, we'll use engineered AI prompts to generate the exact code we need — precisely and instantly.
How the Footer Reveal Effect Actually Works
Before we use AI to generate the code, it helps to understand the underlying illusion. There are two core techniques:
- The CSS-only approach: The footer is set to
position: fixed; bottom: 0; z-index: 0. The main content wrapper gets az-index: 1, a solid background, and amargin-bottomequal to the footer's height. As you scroll down, the main content slides up and over the footer, revealing it at the page end. - The GSAP parallax approach: We add a
ScrollTriggeranimation to the fixed footer that translates it on the Y-axis as the scroll progresses. This creates a depth illusion — the footer appears to slowly rise up from behind the content rather than simply appearing.
Prompt 1: The CSS Curtain Reveal (No JavaScript)
Start with the pure CSS version. This is the structural foundation that every other version builds on. The key insight: it's the main content that needs the magic CSS, not the footer. Use this prompt with ChatGPT-4o or Claude 3.5 Sonnet:
"Act as a Senior Frontend Web Designer. Write a React layout structure using Tailwind CSS v3 that creates a 'Footer Reveal' curtain effect where the footer appears fixed at the bottom of the viewport. Requirements: (1) The root layout wrapper should use React's useRef and useLayoutEffect to measure the footer's computed height and dynamically apply it as the main content's margin-bottom. (2) The footer must be position: fixed, bottom: 0, z-index: 0. (3) The main content wrapper must have z-index: 10, a solid background (bg-white dark:bg-gray-950), and relative positioning. (4) Include a ResizeObserver cleanup in the useEffect return to prevent memory leaks. (5) All components must be TypeScript-safe."Why this prompt works: We've specified exact requirements (ResizeObserver, TypeScript, specific z-index values) that generic "footer reveal" prompts miss. These are the exact edge cases that cause the effect to break on mobile devices.
Prompt 2: Adding the GSAP ScrollTrigger Parallax
The CSS version is clean, but it's flat. To upgrade to award-winning quality, we animate the footer's position as it's revealed. This requires the @gsap/react package and the ScrollTrigger plugin:
"Using the '@gsap/react' package with the useGSAP hook (not the legacy useEffect pattern), write a React Footer component that implements a ScrollTrigger-based parallax reveal animation. When the user scrolls past the main content and the fixed footer begins to appear, animate the footer's translateY from -80px to 0px with scrub: true bound directly to scroll progress. Register the ScrollTrigger plugin inside the component with gsap.registerPlugin(). The trigger element should be the document body's bottom. Include proper cleanup in the useGSAP hook's return function. Write this as a named TypeScript export."The critical difference here is scrub: true. Without this, GSAP plays the animation once and it looks jarring. With scrub: true, the animation speed directly maps to scroll speed, creating a fluid, natural-feeling parallax that no CSS transition can replicate.
Prompt 3: The Full Next.js App Router Integration
If you're using Next.js 14+ with the App Router, you'll run into an additional constraint: GSAP and ScrollTrigger must be initialized only on the client. The safe pattern is using 'use client' and lazy initialization. Use this prompt to get a production-ready App Router version:
"Write a Next.js 14 App Router-compatible React component file with the 'use client' directive that implements a sticky footer reveal using GSAP ScrollTrigger. The footer must: (1) Be exported as a default component named 'RevealFooter'. (2) Use the useGSAP hook from '@gsap/react' for proper React 18 concurrent mode compatibility. (3) Pin the main content to the top of the viewport while the footer slides up using GSAP's pin feature. (4) Include a data-speed attribute on the footer for easy parallax speed customization. (5) Gracefully handle SSR by wrapping GSAP initialization in a typeof window !== 'undefined' check. (6) Import styles correctly from 'gsap/ScrollTrigger'."Pro Tips: The Gotchas No Tutorial Mentions
⚠️ Dynamic Height is Non-Negotiable
Never hardcode the footer height. Footers are constantly different heights across breakpoints, especially if they include newsletter signups, multi-column layouts, or legal text. Use a ResizeObserver on the footer element to recalculate and apply margin-bottom dynamically. Always.
💡 ScrollTrigger.refresh() After Hydration
In Next.js, the DOM often re-renders slightly after the initial paint as hydration completes. Call ScrollTrigger.refresh() inside a short setTimeout (100–200ms) after component mount to ensure GSAP's scroll calculations are based on the final, hydrated DOM. Otherwise, the trigger positions will be off.
🎨 Background Color Matters
The main content must have an explicit, solid background color — not transparent. If it's transparent, the footer (which is beneath the content in the stacking order) will bleed through and you'll see both layers simultaneously. In Tailwind: bg-white dark:bg-gray-950 on your main content wrapper is the pattern.
📱 Mobile Safari Has Edge Cases
iOS Safari has a quirk with position: fixed and the browser chrome (address bar) appearing/disappearing as you scroll. Use 100dvh (dynamic viewport height) instead of 100vh where possible, and test on a real iOS device, not just Chrome DevTools mobile emulation.
What the AI Generates: A Real Code Example
After running Prompt 1 through Claude 3.5 Sonnet, here's the type of clean, production-ready output you should expect:
'use client';
import { useState, useEffect, useRef } from 'react';
export function RevealLayout({ children, footer }: {
children: React.ReactNode;
footer: React.ReactNode;
}) {
const footerRef = useRef<HTMLElement>(null);
const [footerHeight, setFooterHeight] = useState(0);
useEffect(() => {
const observer = new ResizeObserver(entries => {
for (const entry of entries) {
setFooterHeight(entry.contentRect.height);
}
});
if (footerRef.current) {
observer.observe(footerRef.current);
}
return () => observer.disconnect();
}, []);
return (
<>
<div
className="relative z-10 bg-white dark:bg-gray-950"
style={{ marginBottom: footerHeight }}
>
{children}
</div>
<footer
ref={footerRef}
className="fixed bottom-0 left-0 right-0 z-0 bg-gray-900"
>
{footer}
</footer>
</>
);
}Notice how the AI correctly implemented the ResizeObserver with cleanup, the dynamic margin calculation, and the proper z-index stacking — all the things you'd typically need to debug manually.
Frequently Asked Questions
Q: Do I need GSAP Pro / Club GreenSock to use ScrollTrigger?
A: No. ScrollTrigger is now included in the standard GSAP npm package (gsap ≥ 3.6). You just need to install gsap and run gsap.registerPlugin(ScrollTrigger). The free version has everything needed for the footer reveal effect.
Q: Will this affect my Lighthouse performance score?
A: Minimally. GSAP is highly optimized and runs animations on the compositor thread where possible. The bigger performance concern is shipping a large GSAP bundle for a single effect — consider using dynamic imports (import('gsap/ScrollTrigger')) to code-split and only load it when needed.
Q: Can I use Framer Motion instead of GSAP for the same effect?
A: Framer Motion's useScroll() and useTransform() hooks can achieve a similar result, but with less fine-grained control. GSAP's scrub: true gives you frame-perfect control tied directly to scroll position. For true production-quality footer reveals, GSAP is the professional standard.
Naveen Teja Palle
Cloud & DevOps Engineer · Frontend Architect
Cloud & DevOps Engineer specializing in AWS infrastructure, React frontend architecture, and AI workflow automation. I build production-grade tools and write deep-dive tutorials to help developers ship faster and smarter with AI.
Need More GSAP, Three.js & Framer Motion Prompts?
Browse 1,000+ tested frontend animation prompts designed specifically for React developers and UI engineers. Copy, paste, and ship.
Explore Web Component Prompts →