DEV Community

Keymel Gaston
Keymel Gaston

Posted on

I Went Looking for Why Lenis Beat Locomotive Scroll. The Real Story Surprised Me.

I use Lenis for smooth scroll in most of my projects, and I'd always assumed it just won a popularity contest against Locomotive Scroll — more stars, more downloads, moved on. So I went looking for the actual reason. What I found was more interesting than "it's more popular," and it ends with a twist I didn't expect.

Act 1: The problem nobody was talking about

For years, most smooth-scroll libraries — including older versions of Locomotive Scroll — used what's basically a clever hack: fix a wrapper element, then apply a CSS transform to it on every frame, based on an eased scroll value. It looks smooth. It works.

It also means the page never actually scrolls. The browser's real scroll position stays put; you're just visually translating content around.

That hack quietly breaks a handful of things developers don't notice until they ship:

  • position: sticky — stops working correctly, because the element isn't really moving through a real scroll container
  • scroll-snap — same problem
  • Native browser search (Ctrl+F) and anchor links — can behave unpredictably when the "scroll" is fake
  • Screen readers and accessibility tooling — lose meaningful context
  • GPU load — large, repeated transforms aren't free

Lenis took a different approach on purpose: keep the browser's real, native scroll active, and layer interpolation on top of it — actual scrollTo calls, eased, not a transform illusion. From Lenis's own site:

"What began as an internal tool for syncing WebGL and the DOM is now the default smooth scroll across the industry — even powering libraries like Locomotive Scroll. The smoothness was a happy accident."

That's the origin story, by the way — Lenis wasn't built to "win" the smooth-scroll library wars. It was an internal tool at a WebGL agency (darkroom.engineering) for syncing DOM scroll with WebGL canvases, and the smooth-scroll behavior came along for the ride.

Act 2: The twist

Here's the part that surprised me. I went looking for a "Locomotive Scroll vs Lenis, which is better" comparison. What I found instead: Locomotive Scroll v5 is built on top of Lenis.

Not "inspired by." Not "similar architecture." Built on it. Their own release notes say it directly:

"Version 5 is a complete rewrite of Locomotive Scroll, now built on top of Lenis."

And their docs summarize their own history bluntly: "This library has evolved considerably over the years. From jQuery to vanilla ES6, from custom engines to Lenis foundation."

The reasons they list for the rewrite read like a direct admission of the exact problems the old transform-hack approach caused:

  • "No more greedy CSS transforms breaking your layouts"
  • "Works perfectly with position: sticky — No conflicts, no workarounds"
  • Bundle size dropped from ~12.1kB to 9.4kB gzipped

This isn't really a story about one library beating another. It's a story about the ecosystem converging on a better-solved primitive. Locomotive didn't lose — they made the pragmatic call to stop maintaining their own lower-level scroll engine (which had real, filed bugs — GitHub issues #519 and #532, among others) and build their higher-level features (parallax, intersection detection) on top of infrastructure the community had already gotten right.

For context on scale: Lenis sits at roughly 14k GitHub stars with 35 contributors, npm downloads growing from ~93k/month to ~343k/month over the past year. Locomotive Scroll has ~8.6k stars, 25 contributors. Not a landslide — but a clear enough gap that "we'll build on the leader" made sense for Locomotive's team.

Act 3: The thing that might make this whole comparison irrelevant

While Lenis and GSAP's ScrollTrigger were winning their category, the browser itself started doing some of this natively. CSS now has animation-timeline: scroll() and animation-timeline: view() — scroll-driven animations with zero JavaScript.

.reveal {
  animation: fade-in linear;
  animation-timeline: scroll();
  animation-range: entry 0% cover 30%;
}
Enter fullscreen mode Exit fullscreen mode

Chrome's had full support since 2023. Safari joined in September 2025. And this is real enough that a design agency wrote publicly: "We've removed framer-motion from three client sites this year because of them [native scroll-driven animations]." That's not a hypothetical threat — that's a JS animation library actually getting removed from production sites.

But — and this is the part that matters — it's not a clean "native CSS wins" story either. The nuance, well put by one source I found:

"Use native CSS when the animation is linear, depends on scroll or viewport position, and doesn't require programmatic timeline control (play, pause, reverse, scrub) or complex sequencing. GSAP remains necessary for advanced animation sequencing, reverse timelines with speed control, and custom physics."

And specifically for Lenis: native scroll-driven animations sync an animation's progress to scroll position. They don't smooth the scrolling motion itself. That's a different job — the one Lenis actually does. Native CSS doesn't touch it.

There's also a real reason this took Firefox until 2026 to catch up (still behind a flag in stable, as of writing). I checked Mozilla's own bug tracker — their official standards position is supportive, this isn't a "we disagree with the spec" situation. It's scale: the meta-bug tracking implementation has 30+ dependent sub-bugs, including real correctness issues (one engineer explicitly blocked shipping on a bug involving scroll animations breaking a common CSS custom-property technique) that Chrome's larger engineering team could parallelize through faster. A frustrated developer's post on Mozilla Connect noted a related, older bug has been open for almost a decade.

Where that leaves things

Lenis didn't win by being more popular — it won by fixing a real architectural problem (fake scroll breaking accessibility and native browser features) that its "competition" eventually admitted to having too, and built on top of instead of continuing to fight. Meanwhile, native CSS is genuinely eating the simple end of scroll animation — the reveals, the parallax, the progress bars — while leaving the complex, sequenced, physics-driven work (and the actual job of smoothing scroll itself) untouched.

It's not a popularity contest and it's not "native CSS will kill JS libraries" either. It's two different tools settling into the jobs they're actually good at.


I write about this stack (Astro + GSAP + Lenis) semi-regularly — my last post covered why Astro can't type named slots yet, and the one before that covered 4 production bugs common to this exact combo. If you've got a scroll-animation war story of your own, I'd genuinely like to hear it in the comments.

Top comments (0)