Web Design and Engineering

Immersive web stack in 2026: Lenis, GSAP, and what to skip

Lenis (3 kB), GSAP free since April 2025, ScrollTrigger for scroll math, and native CSS scroll-driven animations. The 2026 stack we ship in production.

May 28, 20268 min read
Streaks of light from a moving train at night.

An immersive web stack is a small set of motion libraries that handles smooth scroll, scroll-bound animation, and component transitions for a marketing site or product landing. In 2026 the right set is smaller than it was two years ago. Webflow acquired GSAP and made every plugin free in April 2025. Lenis consolidated into a single maintained package under Darkroom Engineering. Chromium-based browsers and Safari 18 now ship CSS scroll-driven animations natively. The result: most sites need two libraries plus a CSS feature, not five libraries plus a build pipeline.

Below is the stack we ship in production for marketing pages, product landings, and case-study sites. We pick by job, not by brand. The criteria are bundle weight (every kB delays LCP), React 19 plus Next.js 16 App Router compatibility, a maintenance signal in 2026, an honest prefers-reduced-motion path, and zero licensing cost.

What we measured

  • Bundle weight. Anything that ships in the main chunk eats into LCP. We count gzipped size at the import surface we actually use, not the headline number on the homepage.
  • React 19 plus Next.js 16 App Router. Server Components first. Client islands only where motion lives.
  • Maintenance signal. Last release within six months, open issues triaged, owner identifiable.
  • prefers-reduced-motion. The library either respects the media query out of the box or makes opting out trivial. Animation that ignores vestibular disorders fails the accessibility floor.
  • Cost. Free for commercial use, no Club tier, no audit risk.

1. Lenis (smooth scroll)

Lenis is a 3 kB smooth-scroll library from Darkroom Engineering, the team formerly known as Studio Freight. It hijacks native scroll, applies easing on the scroll position, and exposes a tick callback that other libraries hook into. The 1.3.x line is the current production target, with lenis/react as the React adapter. The @studio-freight/react-lenis package was retired in the consolidation.

What it solves. The jittery, page-bound feel of native scroll on long marketing sites. Lenis turns scroll into a continuously animated value, which is the precondition for every parallax effect, sticky transition, and scroll-velocity flourish you see on award sites.

Where it falls short. Lenis takes ownership of the scroll loop. Anchor scrolling, native overscroll bounce on iOS, and accessibility tools that rely on native scroll behavior all need extra handling. On a docs site or a SaaS dashboard, Lenis is overhead. Skip it.

Who it is for. Marketing sites, product landings, and case-study pages where the scroll itself is part of the brand.

2. GSAP core (animation engine)

GSAP is the canonical JavaScript animation engine. Its core is roughly 27 kB gzipped, optimized around requestAnimationFrame, and the timeline API has no real equivalent in any other library. On April 30, 2025, Webflow (which acquired GSAP in late 2024) released the entire library, including every previously paid Club plugin, under a standard license that covers commercial use at no cost. SplitText, MorphSVG, MotionPath, DrawSVG, and ScrollSmoother are all free now. The original GreenSock team maintains GSAP full-time at Webflow.

What it solves. Sequenced, performant animation over arbitrary properties (CSS, SVG, canvas, three.js). When you need a timeline with 12 staged steps that pauses on hover and reverses on click, GSAP is the only mature option that does it without dropping frames.

Where it falls short. Imperative API. You write animation code, you do not declare it. For component-level enter and exit, Motion (the React-friendly successor to Framer Motion) is more ergonomic.

Who it is for. Any site with more than one scroll-triggered section, or a hero that needs more than a CSS keyframe.

3. GSAP ScrollTrigger (scroll-bound positions)

ScrollTrigger is the GSAP plugin that binds a timeline to a scroll position, a viewport intersection, or a Lenis tick. Same license as core (free). It is the part of the stack that does the math: pin this element from 200 px to 800 px of scroll, scrub this timeline as the user passes through, fire this callback when this trigger enters the viewport.

What it solves. The positional logic of scroll-driven sequences. Pinning, scrubbing, snapping, batching, parallax. You can do most of these in 2026 with pure CSS for simple cases (see next section), but ScrollTrigger handles the cases CSS cannot: timelines that span multiple sections, scroll-velocity reads, callbacks that fire JavaScript at a scroll point.

Where it falls short. The integration with Lenis is well-documented but fragile. You synchronize Lenis's scroll to ScrollTrigger.update, you put Lenis's raf on GSAP's ticker, and you disable GSAP lag smoothing. Get one of the three wrong and scrolling decouples from animation. The pattern is solved, but it is configuration debt, not magic.

Who it is for. Any site that pins, scrubs, or sequences on scroll. If the answer is "we only need a fade-in on scroll into view", use CSS instead.

4. CSS scroll-driven animations (native)

Since Chrome 115 (2023) and Safari 18 (2024), CSS supports animation-timeline: scroll() and animation-timeline: view(). These run on the compositor thread, ship zero JavaScript, and degrade gracefully where unsupported. MDN's guide covers the syntax in full. Firefox still requires a flag, but Firefox is now under 3% of global traffic on most B2B SaaS audiences.

What it solves. Fade-on-enter, parallax backgrounds, reading-progress bars, sticky-section transitions, anything where the animation is a function of either the scroll position or the element's visibility in the viewport. With @supports (animation-timeline: view()) you can ship the CSS version and keep a JavaScript fallback for Firefox only.

Where it falls short. No callback API. You cannot read scroll velocity, you cannot fire arbitrary JavaScript at a scroll point, you cannot run a timeline that affects three elements at different rates from the same trigger. For those, ScrollTrigger.

Who it is for. Every site, for the cases that fit. Used as a baseline, native CSS removes 30 to 90 kB of JavaScript from the average marketing page.

5. Motion (formerly Framer Motion)

Motion (the project formerly published as framer-motion) is the React-native animation library for component-level transitions, layout animations, exit animations, and gestures. Roughly 30 kB gzipped with layout animations and AnimatePresence included. It is declarative: you write animate={{ x: 100 }} on a component, the library handles the rest.

What it solves. UI animation. Modals that enter and exit cleanly, layout transitions when items reorder, drag-and-drop, list animations. The cases where you would otherwise reach for React state plus CSS classes plus setTimeout.

Where it falls short. Scroll-bound animation at scale. With 60+ animated elements on a single page or a 15-step scroll timeline, Motion drops frames because every animation tick runs through React's lifecycle. GSAP wins those cases on architecture alone.

Who it is for. SaaS apps with layout transitions, marketing sites that need a few elegant modals or hover micro-interactions. Pair with GSAP if the same page also runs a heavy scroll sequence.

6. View Transitions API (native page transitions)

Browser-native API for animating between two DOM states, or between two pages with cross-document support landing in Chrome and Safari through 2025. Zero library cost, full integration with the rendering pipeline.

What it solves. Page-to-page transitions on multi-page sites without a router-managed shadow DOM. Cross-document View Transitions remove the last technical reason to ship a client-side router on a content site.

Where it falls short. Firefox support is still uneven, and the API requires careful cleanup when state changes mid-transition. Not a substitute for layout animation inside a single page.

Who it is for. Content sites and marketing pages where the brand benefits from continuity between routes.

The comparison

ToolSize (gzip)JobCostLenis~3 kBSmooth scroll loopFree (MIT)GSAP core~27 kBTimeline animationFree (since Apr 2025)ScrollTrigger~12 kBScroll-bound mathFree (since Apr 2025)CSS scroll-driven0 kB JSCompositor-thread scroll FXNativeMotion~30 kBReact component animationFree (MIT)View Transitions0 kB JSPage-to-page morphNative

How to choose

The decision tree we follow on every project:

  • SaaS dashboard or product app. Motion only, for layout transitions and modal entrance. No Lenis, since it interferes with native scroll affordances inside data tables and dashboards. CSS scroll-driven animations for any decorative scroll behavior.
  • Marketing page with one or two animated sections. CSS scroll-driven animations only. Skip the JavaScript stack entirely.
  • Marketing page or product landing with parallax, pinned sections, or scroll-driven storytelling. Lenis plus GSAP ScrollTrigger. Keep Motion out unless you also have layout transitions.
  • Case-study page or long-form editorial site. Full stack: Lenis, GSAP, ScrollTrigger, CSS scroll-driven animations as baseline, Motion for component-level pieces. This is the case where the budget pays for itself.
  • Documentation or content site. CSS only. Lenis breaks anchor-link scrolling and screen-reader navigation. Anything more is decorative debt.

The accessibility floor

Every animation in this stack must respect prefers-reduced-motion. GSAP ships gsap.matchMedia(), which lets you scope an entire ScrollTrigger setup to a media query and revert it automatically when the query no longer matches. Motion respects the user preference via the useReducedMotion hook. CSS scroll-driven animations should sit inside @media (prefers-reduced-motion: no-preference) blocks. Lenis exposes flags you can disable for reduced-motion users so native scroll resumes.

Animation that ignores vestibular disorders is not a feature trade-off, it is an accessibility failure. Ship the reduced-motion path first; the animated variant is enhancement.

Sources

Photo by Maitreya Parab on Unsplash

Frequently asked questions

Do I still need Lenis if CSS scroll-driven animations work natively?
It depends on whether you want smooth-scroll feel or scroll-driven effects. CSS scroll-driven animations replace ScrollTrigger for many fade-in and parallax cases, but they animate based on scroll position only. They do not change how the scroll itself feels. Lenis adds momentum and easing to the scroll-wheel reading. If your design brief calls for a fluid, decelerating scroll, you still need Lenis. If the design only needs elements to react as they enter the viewport, CSS alone is enough.
Is GSAP completely free for commercial projects in 2026?
Yes. On April 30, 2025, Webflow (which acquired GSAP in late 2024) released the entire library, including every previously paid Club plugin like SplitText, MorphSVG, MotionPath, DrawSVG, and ScrollSmoother, under a standard license that covers commercial use at no cost. The license applies regardless of whether the project runs on Webflow or elsewhere, and the original GreenSock team maintains GSAP full-time at Webflow.
Does Lenis hurt Core Web Vitals?
Lenis itself is about 3 kB gzipped and runs after first paint, so its direct impact on LCP is small. The risk is indirect: Lenis hijacks the scroll loop, which means any layout shift, image decode, or third-party script that runs during scroll will be felt more sharply by the user. Audit Lenis sites for CLS and INP, not LCP. If INP regresses, reduce the number of scroll-bound effects rather than removing Lenis.
How do I handle prefers-reduced-motion across this stack?
Wrap every GSAP ScrollTrigger setup inside gsap.matchMedia() with a (prefers-reduced-motion: no-preference) query. For Motion, gate animated components with the useReducedMotion hook and serve a static variant when reduced motion is preferred. Put CSS scroll-driven animations inside an @media block with the same query. For Lenis, expose a toggle that calls lenis.stop() and lets native scroll take over for users who request reduced motion. Ship the reduced-motion variant first; the animated variant is enhancement.

Studio

Start a project.

One partner for the digital product you need to build. Faster delivery, modern tech, lower costs. One team, one invoice.