Threads · note 01 / 4 · by Vorluno · Sep 21, 2026
A stopped Lenis still eats the wheel
You opened a full-screen menu, stopped the page's smooth scroll, and now the menu itself will not scroll. Nothing is broken. Lenis is doing exactly what it says.
- #lenis
- #scroll
- #menu
The symptom
A full-screen menu inside ``, position: fixed, overflow: auto. The page underneath uses Lenis for the wheel. When the menu opens we call lenis.stop() so the page stays put. The menu has more content than the viewport — and the wheel does nothing inside it. Touch works. Keyboard works. The wheel is dead.
The cause, in the source
Lenis 1.3.26, onVirtualScroll: after it walks the event's composedPath() looking for data-lenis-prevent, it checks if (this.isStopped || this.isLocked) { event.preventDefault(); return }. A stopped instance still listens to the wheel on the whole document and cancels the event — so your nested scroll container never receives it. Stopping Lenis is not the same as Lenis stepping aside.
The fix that holds
Two lines, both in the direction the library already points:
{/* the page instance skips this subtree */}
…
// while the menu is open: its own instance, same feel as the page (lerp 0.06, 0.7×)
const menuLenis = new Lenis({ wrapper: panel, content: cuerpo, lerp: 0.06, wheelMultiplier: 0.7, autoRaf: true });
// on close: menuLenis.destroy()
data-lenis-prevent is checked before the stopped branch, so the page instance returns early; the nested instance owns the wheel inside the panel. Touch stays native (no syncTouch), which is what a phone wants.
What the test asserts
Not "the menu scrolls" — that passed with element.scrollTo, which bypasses Lenis entirely and hid the bug for a day. The test sends real wheel events (page.mouse.wheel) and checks that the panel's scrollTop moved and the page's scrollY did not.
// next noteThe dot grid that froze the phone