@studio-freight/lenis-test
v0.1.1
Published
[![LENIS](https://assets.darkroom.engineering/lenis/header.png)](https://github.com/darkroomengineering/lenis)
Downloads
16
Readme
Introduction
This is our take on smooth scroll, lightweight, hard-working, smooth as butter scroll. See Demo.
Installation
JavaScript
using a package manager:
npm i lenis
import Lenis from 'lenis'
using scripts:
<script src="https://unpkg.com/[email protected]/dist/lenis.min.js"></script>
Setup
Basic:
const lenis = new Lenis()
lenis.on('scroll', (e) => {
console.log(e)
})
function raf(time) {
lenis.raf(time)
requestAnimationFrame(raf)
}
requestAnimationFrame(raf)
GSAP ScrollTrigger:
const lenis = new Lenis()
lenis.on('scroll', (e) => {
console.log(e)
})
lenis.on('scroll', ScrollTrigger.update)
gsap.ticker.add((time)=>{
lenis.raf(time * 1000)
})
gsap.ticker.lagSmoothing(0)
React:
See documentation for lenis/react.
Instance settings
| Option | Type | Default | Description |
|----------------------|-----------------------|----------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| wrapper
| HTMLElement, Window
| window
| The element that will be used as the scroll container |
| content
| HTMLElement
| document.documentElement
| The element that contains the content that will be scrolled, usually wrapper
's direct child |
| eventsTarget
| HTMLElement, Window
| wrapper
| The element that will listen to wheel
and touch
events |
| 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 |
| syncTouch
| boolean
| false
| Mimic touch device scroll while allowing scroll sync (can be unstable on iOS<16)
| syncTouchLerp
| number
| 0.075
| Lerp applied during syncTouch
inertia |
| touchInertiaMultiplier
| number
| 35
| Manage the the strength of syncTouch
inertia |
| wheelMultiplier
| number
| 1
| The multiplier to use for mouse wheel events |
| touchMultiplier
| number
| 1
| The multiplier to use for touch events |
| normalizeWheel
| boolean
| false
| Normalize wheel inputs across browsers (not reliable atm) |
| infinite
| boolean
| false
| Enable infinite scrolling! (See example) |
| autoResize
| boolean
| true
| Resize instance automatically based on ResizeObserver
. If false
you must resize manually using .resize()
|
Instance Props
| Property | Type | Description |
|-------------------------|---------------|-------------------------------------------------------------|
| animatedScroll
| number
| Current scroll value |
| dimensions
| object
| Dimensions instance |
| direction
| number
| 1
: scrolling up, -1
: scrolling down |
| emitter
| object
| Emitter instance |
| options
| object
| Instance options |
| targetScroll
| number
| Target scroll value |
| time
| number
| Time elapsed since instance creation |
| actualScroll
| number
| Current scroll value registered by the browser |
| velocity
| number
| Current scroll velocity |
| isHorizontal
(getter) | boolean
| Whether or not the instance is horizontal |
| isScrolling
(getter) | boolean
| Whether or not the scroll is being animated |
| isSmooth
(getter) | boolean
| Whether or not the scroll is animated |
| isStopped
(getter) | boolean
| Whether or not the user should be able to scroll |
| limit
(getter) | number
| Maximum scroll value |
| progress
(getter) | number
| Scroll progress from 0
to 1
|
| rootElement
(getter) | HTMLElement
| Element on which Lenis is instanced |
| scroll
(getter) | number
| Current scroll value (handles infinite scroll if activated) |
| className
(getter) | string
| rootElement
className |
Instance Methods
| Method | Description | Arguments |
|-----------------------------|---------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| raf(time)
| Must be called every frame for internal usage. | time
: in ms |
| scrollTo(target, options)
| Scroll to target. | target
: goal to reachnumber
: value to scroll in pixelsstring
: CSS selector or keyword (top
, left
, start
, bottom
, right
, end
)HTMLElement
: DOM elementoptions
offset
(number
): equivalent to scroll-padding-top
lerp
(number
): animation lerp intensityduration
(number
): animation duration (in seconds)easing
(function
): animation easingimmediate
(boolean
): ignore duration, easing and lerplock
(boolean
): whether or not to prevent the user from scrolling until the target is reachedforce
(boolean
): reach target even if instance is stoppedonComplete
(function
): called when the target is reached |
| on(id, function)
| id
can be any of the following instance events to listen. | |
| stop()
| Pauses the scroll | |
| start()
| Resumes the scroll | |
| resize()
| Compute internal sizes, it has to be used if autoResize
option is false
. |
| destroy()
| Destroys the instance and removes all events. |
Instance Events
| Event | Callback Arguments |
|----------|--------------------|
| scroll
| Lenis instance |
Recommended CSS
html.lenis, html.lenis body {
height: auto;
}
.lenis.lenis-smooth {
scroll-behavior: auto !important;
}
.lenis.lenis-smooth [data-lenis-prevent] {
overscroll-behavior: contain;
}
.lenis.lenis-stopped {
overflow: hidden;
}
.lenis.lenis-scrolling iframe {
pointer-events: none;
}
Considerations
Nested scroll
<div data-lenis-prevent>scroll content</div>
<div data-lenis-prevent-wheel>scroll content</div>
<div data-lenis-prevent-touch>scroll content</div>
Anchor links
<a href="#anchor" onclick="lenis.scrollTo('#anchor')">scroll to anchor</a>
Limitations
- no support for CSS scroll-snap
- capped to 60fps on Safari (source) and 30fps on low power mode
- 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)
Tutorials
- 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
Plugins
- Loconative-scroll by Quentin Hocde
- react-lenis by darkroom.engineering
- r3f-scroll-rig by 14islands
- Lenis Scroll Snap Plugin by Funkhaus
- locomotive-scroll by Locomotive
- vue-lenis by ZEOKKU
- nuxt-lenis by Milkshake Studio
Lenis in use
- Lunchbox by Studio Freight
- Easol 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
- DeSo by Studio Freight
- Francesco Michelini's portfolio by Francesco Michelini
Authors
This set of hooks is curated and maintained by the darkroom.engineering team:
- Clément Roche (@clementroche_) – darkroom.engineering
- Guido Fier (@uido15) – darkroom.engineering
- Leandro Soengas (@lsoengas) - darkroom.engineering
- Franco Arza (@arzafran) - darkroom.engineering