Scroll animation looks amateur when the motion and the scroll position disagree: effects drift behind the page, stutter against smoothed scrolling, or fire at the wrong point. The documented GSAP and Lenis integration addresses this timing mismatch by making one animation loop drive both systems and by telling ScrollTrigger about every smoothed scroll update. It takes only a few lines of code. It cannot make poorly timed, excessive, or inaccessible animation look good.
What each library does
GSAP is an animation library. Its tweens and timelines advance over time, and its global ticker calls your functions once per frame. ScrollTrigger is a GSAP plugin that connects animation progress, or callbacks, to scroll positions. It does not smooth scrolling and it does not take over the page’s scrolling. The ScrollTrigger documentation describes it as a tool that works with native scroll rather than hijacking it.
As an Amazon Associate I earn from qualifying purchases.
Lenis is a separate library that smooths scrolling while keeping the browser’s native scrolling in place. Its project documentation states the goal directly:
PC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minuteRuns on native scroll — wraps the browser’s own scroll, so position: sticky, anchor links, and accessibility keep working.
The two libraries have distinct jobs. Lenis changes how the scroll position moves; ScrollTrigger reads that position and decides which animations should be at which progress. Keeping them in step is the entire purpose of the integration.
#1 Best Overall
- HTML CSS Design and Build Web Sites
- Comes with secure packaging
- It can be a gift option
How do I sync Lenis with ScrollTrigger?
The documented pattern uses two bridges, one in each direction.
Lenis tells ScrollTrigger where the page is
Each time Lenis emits a scroll event, the integration calls ScrollTrigger.update. That call recalculates animation progress from the current scroll position, so triggers use the smoothed position rather than a stale native value. Note the difference between update and refresh: update recalculates progress, while refresh recalculates the start and end positions of triggers. The two are not interchangeable, and the jitter section below depends on that distinction.
GSAP drives Lenis one frame at a time
Lenis needs a call to its raf method on every frame. The integration places that call inside the GSAP ticker, so GSAP’s loop is the only frame loop. The ticker passes its time argument in seconds, but lenis.raf() expects milliseconds, which is why the callback multiplies by 1000.
How do I use Lenis with GSAP ScrollTrigger?
Use the following steps. The code matches the GSAP ticker example in the Lenis project documentation, with the GSAP registration and import lines added.
- Install the packages. Prefer your package manager over CDN links. The Lenis repository’s CDN examples showed version 1.3.26 when checked in early October 2026, but confirm the current version and API before installing.
npm install gsap lenis - Import and register ScrollTrigger before you create any triggers, and import the Lenis stylesheet the project documents.
- Create one Lenis instance with default options and do not enable
autoRaf. The GSAP ticker will own the loop. - Connect Lenis’s scroll event to
ScrollTrigger.update. - Add a ticker callback that calls
lenis.raf(time * 1000). - Decide on lag smoothing. The example includes
gsap.ticker.lagSmoothing(0); the scope of that choice is explained below.
import { gsap } from 'gsap';
import { ScrollTrigger } from 'gsap/ScrollTrigger';
import Lenis from 'lenis';
import 'lenis/dist/lenis.css';
gsap.registerPlugin(ScrollTrigger);
const lenis = new Lenis();
lenis.on('scroll', ScrollTrigger.update);
gsap.ticker.add((time) => {
lenis.raf(time * 1000);
});
gsap.ticker.lagSmoothing(0);
Keep autoRaf and the custom ticker loop separate. Lenis documents autoRaf as the basic setup and a custom loop as the route to integrated control. Running both against the same instance gives you two owners for one animation loop, which defeats the synchronization this setup exists to provide.
What lagSmoothing(0) changes
By default GSAP smooths over rendering stalls. When a frame gap is long, for example after a heavy task or when a hidden tab resumes, GSAP limits the elapsed time it reports, so tweens do not leap ahead. gsap.ticker.lagSmoothing(0) turns that behavior off.
Rank #3
Three points define its scope:
- It is global. It affects every GSAP tween, timeline, and delayed call on the page, not only the ones driven by Lenis. The GSAP ticker documentation describes this scope.
- It does not improve performance. It does not raise the device’s real frame rate or make rendering faster.
- It changes recovery after a stall. After a long pause, animations resume at their true elapsed position rather than easing forward gradually. Check how your page behaves after a tab is hidden and restored, and keep the setting only if that behavior suits your motion.
Why are my GSAP scroll animations jittery?
The documented integration points to a short list of causes. Check these in order before changing animation values.
- Two loops are running. If
autoRafis enabled and the GSAP ticker also callsraf, Lenis receives competing frame updates. Keep one owner. - The scroll event is not connected. Without
lenis.on('scroll', ScrollTrigger.update), ScrollTrigger can compute progress from a position that no longer matches what is on screen. - Trigger positions are stale. ScrollTrigger calculates start and end positions when triggers are created and when the scroller is resized. It does not continuously recalculate them as the DOM moves. If fonts, images, or late-loaded content change the layout, call
ScrollTrigger.refresh()after the layout settles. - Lag smoothing is off and the tab was idle. With
lagSmoothing(0), animations resume from their true elapsed position after a stall. This can look like a jump, which may be what you see after switching tabs. - Nested scroll areas are not configured. Inner scrollers that are not marked for Lenis can fight the page-level smoothing. See the nested scroll notes below.
- The content sits inside an iframe. Iframes do not forward wheel events, so smooth scrolling over them is limited.
If none of these applies, the cause is usually the animation values themselves, and the next section covers that.
Design and accessibility choices that matter more than the code
A synchronized loop makes motion consistent. It does not decide whether the motion is worth having. Start with a clear purpose for each effect and keep the number of scroll-linked effects small. Smooth scrolling is a motion treatment, not a substitute for good choreography.
Rank #4
- Brand: Wiley
- Set of 2 Volumes
- A handy two-book set that uniquely combines related technologies Highly visual format and accessible language makes these books highly effective learning tools Perfect for beginning web designers and front-end developers
Turn on markers: true during development to see each trigger’s start and end positions. Tune start, end, scrub, and pinning from what the layout actually produces, not from values copied from another page. The ScrollTrigger documentation also covers snap, callbacks, custom scrollers, and responsive media-query support.
Do these 3 things before closing this tab:
1Clear out junk files and repair common Windows errors2Scan for outdated or missing drivers - takes under a minute3Repair Windows errors before they cause bigger problemsReduced motion
Lenis honors the reduced-motion preference by default through its respectReducedMotion: true option. When the user requests reduced motion, smoothing is disabled and programmatic scrolls become immediate. That covers only the scrolling layer. Your authored animations still need their own handling, so use Lenis’s prefersReducedMotion state or a check such as window.matchMedia('(prefers-reduced-motion: reduce)') to simplify or remove them.
Nested scroll areas and anchors
Lenis documents allowNestedScroll for inner scroll containers, but warns that checking the DOM tree on every scroll event can affect performance. The documentation offers two alternatives: data-lenis-prevent attributes on elements that should keep native scrolling, or a prevent callback. Anchor links require enabling the anchors option.
Best Value
Known Lenis limitations
- CSS scroll-snap requires Lenis’s snap plugin.
- Smooth scrolling over iframes is limited because iframes do not forward wheel events.
syncTouchmay behave unexpectedly on iOS before version 16.- Nested scroll containers need correct configuration.
These limits mean the combination is not ideal for every page or device. Test the page on the devices your audience uses before relying on it.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Do I need Lenis with GSAP?
No. ScrollTrigger works without a smooth-scrolling library, and GSAP describes it as not scroll-jacking. Lenis is one of two smooth-scrolling options that fit with GSAP, and the other is GSAP’s own ScrollSmoother. The table compares them.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
| Option | What it is | How scrolling is handled | Touch behavior | Integration with GSAP |
|---|---|---|---|---|
| Lenis | Separate library with documented React, Vue, Framer, and snap packages | Wraps the browser’s native scroll, per its documentation | Has a syncTouch option; may behave unexpectedly on iOS before version 16 |
Explicit GSAP ticker example in its documentation |
| GSAP ScrollSmoother | GSAP plugin built on ScrollTrigger | Moves a content wrapper to catch up with the native scroll position | Does not apply smoothing to touch-only devices by default | Native to GSAP; the wiring pattern is not stated in the ScrollSmoother documentation summarized here |
| ScrollTrigger alone | GSAP plugin with no smoothing layer | Native scroll, not scroll-jacked | Native touch behavior | Not applicable; scrollerProxy() is available for third-party smoothers |
Choose Lenis when you want smoothing that you control directly through its own options and ticker integration. Choose ScrollSmoother when you want a GSAP-native solution and accept its wrapper-based model. Choose ScrollTrigger alone when smoothing is not part of the design. Verify current licensing and access terms on each project’s own site before you commit, because they can change.
Lenis does not make an animation professional on its own. Its value appears when your motion is already well planned and needs to track a smooth scroll position accurately.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




