This is our take on smooth scroll, lightweight, hard working, smooth as butter scroll. See Demo
- Performant
- Lightweight (<4Kb gzipped)
- Run scroll in main thread
- Accessibility (CMD+F page search, keyboard navigation, keep scroll position on page refresh, etc.)
- External RAF
- SSR proof
- Custom scroll easing and duration
Feature | Locomotive-scroll | GSAP ScrollSmoother | Lenis |
---|---|---|---|
Native scrollbar | ❌ | ✅ | ✅ |
Native scroll inputs | ❌ | ✅ | ❌ |
Normalize scroll experience | ✅ | ❌ | ✅ |
Accessibility | ❌ | ❌ | ✅ |
CSS Sticky | ❌ | ❌ | ✅ |
IntsersectionObserver | ❌ | ❌ | ✅ |
Open source | ✅ | ❌ | ✅ |
Built-in animation system | ✅ | ✅ | ❌ |
Size (gzip) | 12.1KB | 26.08KB | 3.6KB |
using package manager:
$ npm i @studio-freight/lenis
import Lenis from '@studio-freight/lenis'
using scripts:
<script src="https://cdn.jsdelivr.net/gh/studio-freight/[email protected]/bundled/lenis.js"></script>
Basic setup
const lenis = new Lenis()
lenis.on('scroll', (e) => {
console.log(e)
})
function raf(time) {
lenis.raf(time)
requestAnimationFrame(raf)
}
requestAnimationFrame(raf)
Option | Type | Default | Description |
---|---|---|---|
wrapper |
`HTMLElement | Window` | window |
content |
HTMLElement |
document.documentElement |
The element that contains the content that will be scrolled, usually wrapper 's direct child |
lerp |
number |
0.1 |
Linear interpolation (lerp) intensity (between 0 and 1) |
duration |
number |
1.2 |
The duration of scroll animation (in seconds). Useless if lerp defined |
easing |
function |
(t) => Math.min(1, 1.001 - Math.pow(2, -10 * t)) |
The easing function to use for the scroll animation, our default is custom but you can pick one from Easings.net. Useless if lerp defined |
orientation |
string |
vertical |
The orientation of the scrolling. Can be vertical or horizontal |
gestureOrientation |
string |
vertical |
The orientation of the gestures. Can be vertical , horizontal or both |
smoothWheel |
boolean |
true |
Whether or not to enable smooth scrolling for mouse wheel events |
smoothTouch |
boolean |
false |
Whether or not to enable smooth scrolling for touch events. Note: We have disabled it by default because touch devices native smoothness is impossible to mimic |
wheelMultiplier |
number |
1 |
The multiplier to use for mouse wheel events |
touchMultiplier |
number |
2 |
The multiplier to use for touch events |
normalizeWheel |
boolean |
true |
Normalize wheel inputs across browsers |
infinite |
boolean |
false |
Enable infinite scrolling! |
Method | Description | Arguments |
---|---|---|
raf(time) |
Must be called every frame for internal usage. | time : in ms |
scrollTo(target, options) |
Scroll to a target. | target : goal to reach
options
|
on(id, function) |
id can be any of the following instance events to listen. |
|
stop() |
Pauses the scroll | |
start() |
Resumes the scroll | |
destroy() |
Destroys the instance and remove all events. |
Event | Callback Arguments |
---|---|
scroll |
scroll : returns scroll position. limit : returns scroll limit. velocity : returns scroll velocity. direction : returns 1 or -1 . |
.lenis.lenis-smooth {
scroll-behavior: auto;
}
Keep html elements default sized, this is necessary for Webflow implementation (see issue).
html.lenis {
height: auto;
}
Use data-lenis-prevent
attribute on nested scroll elements. In addition, we advise you to add overscroll-behavior: contain
on this element.
<div data-lenis-prevent>scroll content</div>
.lenis.lenis-smooth [data-lenis-prevent] {
overscroll-behavior: contain;
}
Manually use lenis.scrollTo('#anchor')
on anchor link click (see issue)
<a href="#anchor" onclick="lenis.scrollTo('#anchor')">scroll to anchor</a>
.lenis.lenis-stopped {
overflow: hidden;
}
lenis.on('scroll', ScrollTrigger.update)
gsap.ticker.add((time)=>{
lenis.raf(time * 1000)
})
- no support for CSS scroll-snap
- capped to 60fps on Safari (source)
- smooth scroll will stop working over iframe since they don't forward wheel events
- position fixed seems to lag on MacOS Safari pre-M1 (source)
- Scroll Animation Ideas for Image Grids by Codrops
- How to Animate SVG Shapes on Scroll by Codrops
- The BEST smooth scrolling library for your Webflow website! (Lenis) by Diego Toda de Oliveira
- Easy smooth scroll in @Webflow with Lenis + GSAP ScrollTrigger tutorial by También Studio
- Wyre by Studio Freight
- Lunchbox by Studio Freight
- Easol by Studio Freight
- Repeat by Studio Freight
- Dragonfly by Studio Freight
- Yuga Labs by Antinomy Studio
- Quentin Hocde's Portfolio by Quentin Hocde
- Houses Of by Félix P. & Shelby Kay
- Shelby Kay's Portfolio by Shelby Kay
- Heights Agency Portfolio by Francesco Michelini
- Goodship by Studio Freight
- Flayks' Portfolio by Félix P. & Shelby Kay
- Matt Rothenberg's portfolio by Matt Rothenberg
- Edoardo Lunardi's portfolio by Edoardo Lunardi
This set of hooks is curated and maintained by the Studio Freight Darkroom team:
- Clément Roche (@clementroche_) – Studio Freight
- Guido Fier (@uido15) – Studio Freight
- Leandro Soengas (@lsoengas) - Studio Freight
- Franco Arza (@arzafran) - Studio Freight