Back to Blog
Next.js · Note

Lenis stops a textarea or dropdown from scrolling

Simon Doba·August 6, 2026·3 min read

A textarea in one of my figures would not scroll. Neither would a table with overflow-y-auto next to it. Clicking into them worked, the keyboard worked, the scrollbar was there — the wheel just did nothing.

The cause is smooth scroll. Lenis intercepts wheel events for the whole document so it can animate the page itself. Anything nested that has its own scrollbar never receives them.

The documented fix

Lenis looks for a data-lenis-prevent attribute and leaves that subtree alone:

<textarea data-lenis-prevent />
<div className="max-h-72 overflow-y-auto" data-lenis-prevent></div>

That works. It also has to be remembered on every scrollable element anyone ever adds. My globals.css had carried the matching rule for months, and a search showed that not one element in the codebase used the attribute — including two figures I had shipped that week.

The fix that does not depend on remembering

Lenis takes a prevent predicate. Instead of tagging elements, ask the node under the cursor whether it scrolls itself:

function isOwnScroller(node) {
  if (node.hasAttribute?.('data-lenis-prevent')) return true;
  if (node instanceof HTMLTextAreaElement) return true;
  if (node instanceof HTMLSelectElement) return true;

  // Only worth a style lookup for elements that actually overflow.
  if (node.scrollHeight <= node.clientHeight) return false;
  const overflowY = window.getComputedStyle(node).overflowY;
  return overflowY === 'auto' || overflowY === 'scroll';
}

const lenis = new Lenis({ prevent: isOwnScroller });

The scrollHeight check comes first on purpose: it is a cheap property read, and it means getComputedStyle only runs for elements that are actually overflowing. The attribute still wins where it documents intent.

Two things worth knowing

  • Horizontal scrollers are usually fine. With orientation: 'vertical', Lenis is not touching horizontal wheel or trackpad events, so a scrollable <pre> or table keeps working. Worth checking rather than assuming if you run it in both directions.
  • It is invisible in development if you skip Lenis on mobile. Mine is disabled under 768px and for prefers-reduced-motion, so a narrow window or a reduced-motion setting hides the bug entirely.

Lenis 1.x with orientation and gestureOrientation both set to vertical, in a Next.js 16 App Router client provider.

Share this article

Building something similar?

I write about setups I actually use. If you're working on something comparable, I'd be curious what your workflow looks like.

Get in touch

Cookie Settings

We use cookies for analytics and to improve our website. Privacy policy