Lenis 平滑滚动库完整指南:从安装到上生产的快速上手
2026/9/11 2:52:34 网站建设 项目流程

Lenis 平滑滚动库完整指南:从安装到上生产的快速上手

【免费下载链接】lenisSmooth scroll as it should be项目地址: https://gitcode.com/GitHub_Trending/le/lenis

Lenis 是一个几 KB、零依赖的轻量平滑滚动库,它包裹浏览器原生滚动来消除原生滚动的生硬顿挫,同时保住 sticky、锚点跳转和键盘可访问性。适合想给网站加平滑滚动、视差或 WebGL 滚动同步的前端开发者,10 分钟可以跑通。

为什么不用自己造虚拟滚动:Lenis 解决什么问题

传统平滑滚动两条路都有坑:CSSscroll-behavior: smooth只管程序化跳转,管不住滚轮手感;自己拦截滚轮做虚拟滚动,则会把position: sticky、锚点、浏览器滚动回弹、辅助功能全部打断。Lenis 的做法是"劫持输入、保留轨道"——滚动手感被接管,但滚动本身始终发生在原生滚动轨道上,页面结构不需要任何改造,也不强制改变 DOM 层级(不像部分同类库要求把内容包进 transform 容器)。典型场景:WebGL 场景滚动驱动、视差、横向滚动区、分屏锁定式翻页。

最快上手:十行代码接入 Lenis 平滑滚动

npm 安装(yarn/pnpm 同理),没有构建系统则直接在 HTML 里引 CDN 上的dist/lenis.min.jsdist/lenis.css

npm i lenis
import Lenis from 'lenis' import 'lenis/dist/lenis.css' // 必须,否则停止态/iframe 行为不对 const lenis = new Lenis({ autoRaf: true, // 内置 rAF 循环,省去手写 requestAnimationFrame }) lenis.on('scroll', (e) => { // e.velocity / e.progress / e.direction,可驱动任意动画 })

不开autoRaf时需要自己驱动每帧更新,这是官方文档里最常见的排错项,先记住:

const lenis = new Lenis() function raf(time) { lenis.raf(time) requestAnimationFrame(raf) } requestAnimationFrame(raf)

工作原理:接管滚轮输入,逐帧插值滚动位置

核心逻辑在 核心实现 里,文件头部有作者自己写的五步注释,直接照它理解即可:

  1. 监听容器的wheel/touch事件,并preventDefault阻止原生滚动(事件归一化在 VirtualScroll);
  2. 把归一化后的 delta 累加到目标值targetScroll
  3. 每帧由 Animate 类 把当前值animatedScrolltargetScroll逼近——默认用指数衰减的damp插值(lerp),指定duration+easing时切换为时间基缓动;
  4. 算出的新位置通过scrollTo({ behavior: 'instant' })写回浏览器,也就是滚动始终跑在原生滚动轨道上;
  5. 没有平滑动画在跑时,Lenis 退化为监听原生scroll事件被动同步。

这套设计的直接收益:position: sticky、锚点定位、屏幕阅读器对滚动条的感知都不受影响;副作用是 iframe 内拿不到滚轮事件(它不转发),官方 CSS 里顺手把平滑滚动期间的 iframe 设成了pointer-events: none

最常被调的 6 个参数及默认值

完整选项见 官方文档 的 Settings 表,先认这 6 个:

参数作用默认值
lerp滚轮输入的插值强度,越小越"飘"0.1
duration程序化滚动动画时长(秒),设了easing后生效1.2
easing缓动函数,任意(t) => t形态的函数内置自定义曲线
smoothWheel是否平滑滚轮事件(false时触摸仍可平滑)true
orientation滚动轴,vertical/horizontalvertical
autoRaf是否内置 rAF 循环,false必须手动raf(time)false

另外两个高频开关:anchors: true接管锚点链接走平滑跳转;allowNestedScroll: true让页面内嵌套滚动容器(侧栏、弹窗里的列表)保留原生滚动——但它在每次滚动事件时都要检查 DOM 树,有性能开销,注意下面"上生产前"那节。

主流框架组合:React、Vue 与 GSAP 的最小接线

Lenis 对每个框架都有一等适配包,实例通过 context 下发,不用手动传 prop。

React(lenis/react):

import { ReactLenis, useLenis } from 'lenis/react' function App() { const lenis = useLenis((lenis) => { // 每次滚动触发 }) return <ReactLenis root>{/* 页面内容 */}</ReactLenis> }

root属性让实例挂到<html>滚动容器上,并且全局可通过useLenis访问。

Vue / Nuxt(lenis/vue):

// Nuxt: nuxt.config 里加一行 modules: ['lenis/nuxt'] // Vue: app.use(LenisVue)
<template> <VueLenis root :options="{ autoRaf: true }" /> </template>

GSAP ScrollTrigger 是它最主要的搭档,关键是把 Lenis 的raf交给 GSAP 的 ticker、让 ScrollTrigger 听 Lenis 的 scroll 事件,两边共享同一个时钟才不会不同步:

lenis.on('scroll', ScrollTrigger.update) gsap.ticker.add((time) => { lenis.raf(time * 1000) // GSAP 给秒,Lenis 要毫秒 }) gsap.ticker.lagSmoothing(0)

配合框架时记得把autoRaf关掉,把raf挂进对应驱动(React 版本示例见 packages/react/README.md 的 GSAP 一节)。做分屏锁定翻页则用 lenis/snap 插件,CSS scroll-snap 在 Lenis 下不生效,别指望它:

import Snap from 'lenis/snap' const snap = new Snap(lenis) snap.addElement(document.querySelector('.section'), { align: 'start' })

上生产前的注意事项:嵌套滚动、iframe 与帧率

  • CSS 必须带lenis.css不止是修饰,它负责停止态的overflow: clipdata-lenis-preventoverscroll-behavior等关键行为,漏掉会有诡异 bug;
  • autoRaf是排错第一怀疑对象:不设autoRaf: true又不手动调lenis.raf(time),页面会完全不滚;
  • 嵌套滚动优先用属性而不是自动检测:给需要原生滚动的容器直接挂data-lenis-prevent(还有-wheel/-touch/-vertical/-horizontal细分版本),比allowNestedScroll的全树检查便宜得多;
  • iframe 内容不会平滑滚:iframe 不向前滚动容器转发 wheel 事件,且平滑滚动期间 iframe 默认不可交互,内嵌视频/地图要有心理预期;
  • 帧率天花板:Safari 封顶 60fps、低功耗模式 30fps(WebKit 已知限制),requestAnimationFrame驱动的库都绕不开;
  • 移动端惯性需显式开启syncTouch让触摸手势也走平滑插值,但 iOS < 16 上行为可能不稳定,上线前在真机验证;
  • SPA 路由切换:跨页跳转前可开stopInertiaOnNavigate: true或手动lenis.reset(),避免旧惯性带着新页面走。

new Lenis({ autoRaf: true })起步,先用scroll事件驱动一个视差动画验证手感,再按项目栈接上 ScrollTrigger 或框架适配包——这条路径走完,平滑滚动就算能进生产了。

【免费下载链接】lenisSmooth scroll as it should be项目地址: https://gitcode.com/GitHub_Trending/le/lenis

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询