Lenis
Smooth scroll as it should be
Install / Use
npx skills add darkroomengineering/lenisInstalls into whichever agent you are using.
README
Introduction
Lenis ("smooth" in latin) is a lightweight, robust, and performant smooth scroll library. It's designed by @darkroom.engineering to be simple to use and easy to integrate into your projects. It's built with performance in mind and is optimized for modern browsers. It's perfect for creating smooth scrolling experiences on your website such as WebGL scroll syncing, parallax effects, and much more, see Demo and Showcase.
Read our Manifesto to learn more about the inspiration behind Lenis.
<br/>- Features
- Sponsors
- Packages
- Showcase
- Installation
- Setup
- No-code usage
- Settings
- Properties
- Methods
- Events
- Considerations
- Limitations
- Troubleshooting
- Tutorials
- Plugins
- License
Features
- Lightweight & dependency-free — the whole library is a few KB with zero runtime dependencies
- Runs on native scroll — wraps the browser's own scroll, so position: sticky, anchor links, and accessibility keep working
- Any axis — smooth vertical, horizontal, and nested scrolling from a single instance
- Built for sync — drives WebGL scroll scenes, GSAP ScrollTrigger, and parallax off one loop
- Framework adapters — first-class packages for React, Vue, and Framer
- Scroll snapping — the snap plugin aligns sections without fighting the smooth scroll
Sponsors
If you’ve used Lenis and it made your site feel just a little more alive, consider sponsoring.
Your support helps us smooth out the internet one library at a time—and lets us keep building tools that care about the details most folks overlook.
<!-- sponsors --><a href="https://www.contentarchitecture.dev/?utm_source=lenis&utm_medium=github"><img src="https://darkroom-lenis-showcase.s3.us-east-1.amazonaws.com/pbc_3665759510/23raiqpdg8nej3m/word_49x1dnfo22.svg" height="96" alt="The Content Architecture"/></a>
<a href="https://glauber.org/?utm_source=lenis&utm_medium=github"><img src="https://github.com/glauber-sampaio.png?size=64" width="64" height="64" alt="Glauber"/></a> <a href="https://smsunarto.com/?utm_source=lenis&utm_medium=github"><img src="https://github.com/smsunarto.png?size=64" width="64" height="64" alt="Scott"/></a> <a href="https://bizar.ro/?utm_source=lenis&utm_medium=github"><img src="https://github.com/bizarro.png?size=64" width="64" height="64" alt="Luis Bizarro"/></a> <a href="https://www.edoardolunardi.dev/?utm_source=lenis&utm_medium=github"><img src="https://github.com/edoardolunardi.png?size=64" width="64" height="64" alt="Edoardo Lunardi"/></a> <a href="https://www.cachet.studio/?utm_source=lenis&utm_medium=github"><img src="https://github.com/cachet-studio.png?size=64" width="64" height="64" alt="cachet.studio"/></a> <a href="https://good-fella.com/?utm_source=lenis&utm_medium=github"><img src="https://github.com/GoodFellaStudio.png?size=64" width="64" height="64" alt="Julian Fella"/></a> <a href="https://oho.design/?utm_source=lenis&utm_medium=github"><img src="https://github.com/OHO-Design.png?size=64" width="64" height="64" alt="OHO Design"/></a> <a href="https://itsoffbrand.com/?utm_source=lenis&utm_medium=github"><img src="https://github.com/itsoffbrand.png?size=64" width="64" height="64" alt="OFF+BRAND."/></a>
<!-- sponsors --> <br/>Packages
<br/>Installation
Using a package manager:
npm i lenis
# or
yarn add lenis
# or
pnpm add lenis
import Lenis from 'lenis'
<br/>
Using scripts:
<script src="https://unpkg.com/lenis@1.3.26/dist/lenis.min.js"></script>
<br/>
Setup
Basic:
// Initialize Lenis
const lenis = new Lenis({
autoRaf: true,
});
// Listen for the scroll event and log the event data
lenis.on('scroll', (e) => {
console.log(e);
});
Custom raf loop:
// Initialize Lenis
const lenis = new Lenis();
// Use requestAnimationFrame to continuously update the scroll
function raf(time) {
lenis.raf(time);
requestAnimationFrame(raf);
}
requestAnimationFrame(raf);
Recommended CSS:
Import stylesheet:
import 'lenis/dist/lenis.css'
Or link the CSS file:
<link rel="stylesheet" href="https://unpkg.com/lenis@1.3.26/dist/lenis.css">
Or add it manually:
GSAP ScrollTrigger:
// Initialize a new Lenis instance for smooth scrolling
const lenis = new Lenis();
// Synchronize Lenis scrolling with GSAP's ScrollTrigger plugin
lenis.on('scroll', ScrollTrigger.update);
// Add Lenis's requestAnimationFrame (raf) method to GSAP's ticker
// This ensures Lenis's smooth scroll animation updates on each GSAP tick
gsap.ticker.add((time) => {
lenis.raf(time * 1000); // Convert time from seconds to milliseconds
});
// Disable lag smoothing in GSAP to prevent any delay in scroll animations
gsap.ticker.lagSmoothing(0);
<br/>
No-code usage
One line, no build step — just drop this into your HTML:
<link rel="stylesheet" href="https://unpkg.com/lenis@1.3.26/dist/lenis.css">
<script src="https://unpkg.com/lenis@1.3.26/dist/lenis.min.js"></script>
<script>new Lenis({ autoRaf: true, autoToggle: true, anchors: true, allowNestedScroll: true, naiveDimensions: true, stopInertiaOnNavigate: true })</script>
That's it, your page now has smooth scrolling and should handle most of the usual issues such as:
- compatibility with other packages
- modals
- smooth anchors
- scroll reset on page change
Settings
| Option | Type | Default | Description |
|-------------------------|----------------------------|----------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| allowNestedScroll | boolean | false | Automatically allow nested scrollable elements to scroll natively. This is the simplest way to handle nested scroll. ⚠️ Can create performance issues since it checks the DOM tree on every scroll event. If that's a concern, use prevent option instead. |
| anchors | boolean, ScrollToOptions | false | Scroll to anchor links when clicked. If true is passed, it will enable anchor links with default options. If ScrollToOptions is passed, it will enable anchor links with the given options. |
| autoRaf | boolean | false | Whether or not to automatically run requestAnimationFrame loop. |
| autoResize | boolean | true | Resize instance automatically based on ResizeObserver. If false you must resize manually using .resize(). |
| autoToggle | boolean | false | Automatically start or stop the lenis instance based on the wrapper's overflow property, ⚠️ this requires Lenis recommended CSS. Safari > 17.3, Chrome > 116 and Firefox > 128 (https://caniuse.com/?search=transition-behavior). |
| content | HTMLElement | document.documentElement | The element that contains the content that will be scrolled, usually wrapper's direct child. |
| duration | number | 1.2
Related Skills
node-connect
385.5kDiagnose OpenClaw Android, iOS, or macOS node pairing, QR/setup code, route, auth, and connection failures.
imsg
385.5kUse the imsg CLI from OpenClaw agents for iMessage/SMS DMs, groups, replies, reactions, polls, watching, and private-API actions.
Agent Development
140.7kThis skill should be used when the user asks to "create an agent", "add an agent", "write a subagent", "agent frontmatter", "when to use description", "agent examples", "agent tools", "agent colors", "autonomous agent", or needs guidance on agent structure, system prompts, triggering conditions, or…
review-duplication
106.4kUse this skill during code reviews to proactively investigate the codebase for duplicated functionality, reinvented wheels, or failure to reuse existing project best practices and shared utilities.

