Next.js集成Lenis React后overflow元素无法滚动的问题求助
Lenis React集成Next.js后内部滚动元素异常的排查与解决思路
我近期将Lenis React组件集成到Next.js应用中,之后页面上带有overflow-scroll类的元素出现滚动异常,集成前该元素滚动功能完全正常。相关CSS样式为:overflow-y-scroll pr-[17px] box-content。
我尝试过以下方案,但均未解决问题:
- 使用Mantine的ScrollArea组件替代原生滚动容器
- 设置鼠标悬浮时让滚动容器获取焦点
- 自定义基于鼠标位置的滚动逻辑(代码如下),但该逻辑是跟随鼠标位置直接跳转滚动,并非我需要的正常滚动效果
自定义滚动逻辑代码:
useEffect(() => { const element = carouselContainerRef.current; const handleMouseMove = (event) => { if (!isScrolling) return; // Simplified calculations since we're using the ref directly const containerRect = element.getBoundingClientRect(); const deltaY = event.clientY - containerRect.top; const maxScrollTop = element.scrollHeight - element.clientHeight; const newScrollTop = Math.min(Math.max(0, deltaY), maxScrollTop); element.scrollTop = newScrollTop; }; if (element) { element.addEventListener('mousemove', handleMouseMove); } return () => { if (element) { // 注:原代码存在错误,此处应为removeEventListener element.removeEventListener('mousemove', handleMouseMove); } }; }, [isScrolling]);
排查方向
- 检查Lenis的全局滚动拦截:Lenis默认会接管全局滚动事件,可能阻止了内部滚动容器的原生滚动事件冒泡。查看Lenis初始化配置,重点关注
touch、wheel等选项是否影响了内部元素。 - 滚动事件冲突排查:打开浏览器开发者工具的Event Listeners面板,查看滚动容器上的事件监听,确认Lenis是否给它绑定了额外事件或阻止了默认行为。
- CSS样式冲突检查:Lenis可能会给全局或容器添加
pointer-events、touch-action等样式,导致滚动容器无法接收输入事件。检查滚动元素的computed样式,重点看touch-action、pointer-events、overflow相关属性是否被篡改。 - Next.js渲染机制影响:如果滚动容器是服务端渲染的,Lenis在客户端初始化时可能和DOM元素交互存在延迟,导致滚动事件绑定异常。尝试在
useEffect中延迟初始化Lenis,或确保滚动容器在客户端挂载完成后再启用Lenis。
解决思路
- 给内部滚动容器添加Lenis排除规则:Lenis支持通过配置指定不需要接管的元素,两种方式:
- 初始化时配置
exclude选项:const lenis = new Lenis({ exclude: '.overflow-scroll' }) - 给滚动容器添加
data-lenis-prevent属性:<div className="overflow-scroll" data-lenis-prevent>
- 初始化时配置
- 手动阻止事件冒泡到Lenis:在滚动容器上添加事件监听,阻止滚动事件冒泡到Lenis的全局监听:
useEffect(() => { const container = carouselContainerRef.current if (!container) return const handleWheel = (e) => e.stopPropagation() const handleTouchMove = (e) => e.stopPropagation() container.addEventListener('wheel', handleWheel) container.addEventListener('touchmove', handleTouchMove) return () => { container.removeEventListener('wheel', handleWheel) container.removeEventListener('touchmove', handleTouchMove) } }, []) - 调整Lenis配置降低影响:修改Lenis的
smoothWheel、autoResize等配置,比如关闭平滑滚动对wheel事件的处理:const lenis = new Lenis({ smoothWheel: false }) - 修复自定义滚动逻辑:如果要保留自定义逻辑,改成基于滚动增量的正常滚动方式:
useEffect(() => { const element = carouselContainerRef.current if (!element) return const handleWheel = (e) => { e.preventDefault() element.scrollTop += e.deltaY } element.addEventListener('wheel', handleWheel) return () => element.removeEventListener('wheel', handleWheel) }, [])
内容的提问来源于stack exchange,提问作者Alister Sequeira
相关产品推荐
相关产品推荐

