Smooth scrolling can significantly enhance user experience, especially when combined with scroll-triggered animations. Let's explore how to integrate Lenis smooth scrolling with GSAP in a Next.js application.
Installation
First, install the required packages:
pnpm add @studio-freight/react-lenis gsap
Basic Setup
Create a Lenis provider that will wrap your application:
"use client"
import { ReactLenis } from "@studio-freight/react-lenis"
import { useEffect, useRef } from "react"
import { gsap } from "gsap"
interface LenisProviderProps {
children: React.ReactNode
}
export function LenisProvider({ children }: LenisProviderProps) {
const lenisRef = useRef(null)
useEffect(() => {
function update(time: number) {
if (lenisRef.current) {
const lenis = (lenisRef.current as any).lenis
if (lenis?.raf) {
lenis.raf(time * 1000)
}
}
}
gsap.ticker.add(update)
return () => {
gsap.ticker.remove(update)
}
}, [])
return (
<div className="contents">
<ReactLenis ref={lenisRef} root autoRaf={false}>
{children}
</ReactLenis>
</div>
)
}
Integration with Next.js
Update your root layout to include the Lenis provider:
import { LenisProvider } from "@/app/providers/lenis-provider"
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en">
<body>
<LenisProvider>
{children}
</LenisProvider>
</body>
</html>
)
}
Using Lenis with GSAP Animations
Here's how to create scroll-triggered animations that work smoothly with Lenis:
"use client"
import { useRef } from "react"
import { gsap } from "gsap"
import { ScrollTrigger } from "gsap/ScrollTrigger"
import { useLenis } from "@studio-freight/react-lenis"
gsap.registerPlugin(ScrollTrigger)
export function AnimatedSection() {
const containerRef = useRef(null)
// Optional: Use Lenis scroll position
useLenis(({ scroll }) => {
// This callback runs on every scroll
console.log("Scroll position:", scroll)
})
useEffect(() => {
const ctx = gsap.context(() => {
gsap.from(".animate-me", {
opacity: 0,
y: 100,
stagger: 0.2,
scrollTrigger: {
trigger: ".animate-me",
start: "top bottom-=100",
end: "top center",
scrub: true,
},
})
}, containerRef)
return () => ctx.revert()
}, [])
return (
<div ref={containerRef}>
<div className="animate-me">Smooth scroll</div>
<div className="animate-me">With GSAP animations</div>
<div className="animate-me">Just works!</div>
</div>
)
}
Advanced Configuration
You can customize Lenis behavior through options:
<ReactLenis
root
options={{
lerp: 0.1, // Linear interpolation (0-1)
duration: 1.5, // Scroll duration
smoothWheel: true, // Enable smooth scrolling for mouse wheel
wheelMultiplier: 1, // Mouse wheel multiplier
touchMultiplier: 2, // Touch multiplier
infinite: false, // Enable infinite scrolling
}}
>
{children}
</ReactLenis>
Performance Considerations
- Use
useRefandgsap.context()for proper cleanup of GSAP animations - Set
autoRaf: falseand use GSAP's ticker for better performance - Keep animations simple and use
will-changeCSS property judiciously - Test on mobile devices to ensure smooth performance
Conclusion
Lenis and GSAP work together seamlessly to create smooth, performant scroll experiences in Next.js applications. The key is proper initialization and cleanup of both libraries, along with careful consideration of performance implications.
Remember to check out the Lenis documentation and GSAP documentation for more advanced features and options. For React-specific implementations, refer to the GSAP React guide and React Lenis documentation which provide detailed examples and best practices for integrating these libraries in React applications.
This blog post provides a comprehensive guide to integrating Lenis with GSAP in a Next.js application, following the same structure as your existing blog post while focusing on the specific implementation details of smooth scrolling and animations.