Lenis on Windows: the smooth-scroll fix nobody documents
Lenis ships beautifully on macOS and craters on Windows trackpads. The fix is four lines, two of them are easy to miss, and the docs do not mention any of it.

We shipped a portfolio rebuild last week and immediately got a bug report from a Windows user: scrolling felt like the page was fighting back. Stutter, snap, double-scroll, occasional 200px overshoot. On macOS — buttery. On Windows — broken.
Lenis is the smooth-scroll library most studios reach for in 2026. It is fast, small, and the demo on its homepage is gorgeous. What the docs do not tell you is that the default config is tuned for macOS trackpads, and the gap between that experience and a Windows precision-touchpad or scroll-wheel mouse is wide enough to look like a bug in your site.
What actually breaks
Three things go wrong on Windows specifically. First, the default requestAnimationFrame loop Lenis suggests in its README is racy under React 19 + Next 16 — the cleanup runs before the next frame fires and you get a frozen scroll handler. Second, the default lerp value is too aggressive for Windows scroll events, which arrive in larger discrete chunks. Third, route changes do not reset scroll position because Lenis owns the scroll, not the browser — and Next.js stops trying.
The fix
Four changes. The two that matter most are autoRaf: true (Lenis runs its own loop — no React effect to leak) and lerp: 0.14 (slower interpolation, masks the chunkier Windows wheel deltas).
Why each piece matters
autoRaf: true — the single biggest change. Lenis runs its own animation frame loop, so you do not need a separate useEffect that calls lenis.raf(time) on every frame. That older pattern is what most tutorials still show, and it is the source of the frozen-scroll bug under React 19 strict mode — the cleanup function tears down the rAF before the next frame can register the new one.
lerp: 0.14 — Lenis defaults to 0.1 which feels gorgeous on a Magic Trackpad. On a Windows precision touchpad it feels like the page is two frames behind your finger. 0.14 is the value we landed on after testing across three Windows machines: tight enough to feel responsive, slow enough that the chunky deltas average out instead of snapping.
The prefers-reduced-motion and pointer: coarse bail-outs are non-negotiable. Smooth scroll on a phone is jank you are imposing on a device whose hardware already smooths the scroll for you, and bypassing reduced-motion is an accessibility violation. Skip Lenis entirely on both.
The prevent callback lets you opt nodes out — handy for modals, video controls, and any nested scroll container. Annotate them with data-lenis-prevent and Lenis hands the scroll back to the browser. Without this, your dropdown menus do not scroll on Windows. Ask us how we know.
The route-change trap
When you navigate in the Next.js App Router, the browser tries to scroll to the top of the new page. Lenis says no — it owns the scroll position now. You land on the new page already scrolled halfway down. The fix is the second useEffect: listen to pathname, call lenis.scrollTo(0, { immediate: true }), and a lenis.resize() for good measure (layout changes between routes invalidate Lenis’s cached page height).
The pageshow listener handles back/forward navigation. Without it, hitting the back button on a Lenis-controlled page restores the cached DOM but Lenis still thinks the viewport is whatever it was before unmount. lenis.resize() fixes that in one line.
What we did not do
We did not ship a polyfill. We did not detect Windows specifically. We did not write a wheel-event normalizer. Smooth scrolling is one of those features where the right answer is almost always "calibrate the defaults until everyone gets a decent experience" rather than "build a per-platform fork." If we needed any of those things, we would have ripped Lenis out and used the browser’s native scroll behavior with a smaller, targeted scroll-margin pass — and that is still the right move if you have any doubt the engagement justifies the JS budget.
But for a portfolio site where the scroll choreography is part of the brand, four lines of config gets you 95% of the way there. Drop this in, ship it, and watch the Windows bug reports stop coming.
Takeaways
If you remember three things: use autoRaf so Lenis owns its own loop. Bump lerp to 0.14 for cross-platform parity. Hand the scroll back to the browser for prefers-reduced-motion, coarse pointers, and route changes. Everything else is detail.