lenis
Lightweight, smooth scroll library — butter-smooth scrolling without the performance cost of heavy alternatives.
lenis
General JSLightweight, smooth scroll library — butter-smooth scrolling without the performance cost of heavy alternatives.
Fit
Bundle (gzip)
5.4 kB
18.4 kB raw
Install size includes transitive dependencies. Bundle size is gzipped browser payload.
Freshness
The Problem
Native browser scrolling is snappy but has no easing — it stops instantly. Smooth scroll libraries like locomotive-scroll or smooth-scrollbar solve this but:
- They're heavy (adding 50–100KB+ to your bundle)
- They interfere with accessibility tools and keyboard navigation
- They break
position: stickyand other scroll-linked CSS - They're slow on mobile or cause jank on lower-end devices
- Integrating with GSAP or WebGL animations requires complex workarounds
What It Does
Lenis is a minimal (~5KB) smooth scroll library that intercepts native scroll events and replaces the scroll position with a lerped (linearly interpolated) value. It plays nicely with GSAP ScrollTrigger, Three.js, and other animation libraries. Unlike heavier alternatives, it doesn't use a virtual scroll container — so position: sticky, anchor links, and accessibility all work as expected.
With 33K weekly npm downloads, it's a favourite in the creative development community.
Installation
npm install lenisUsage Example
Basic setup (vanilla JS)
import Lenis from "lenis";
const lenis = new Lenis({
duration: 1.2,
easing: (t) => Math.min(1, 1.001 - Math.pow(2, -10 * t)),
smoothWheel: true,
});
// Required: run lenis in your animation loop
function raf(time: number) {
lenis.raf(time);
requestAnimationFrame(raf);
}
requestAnimationFrame(raf);React with useEffect
import { useEffect } from "react";
import Lenis from "lenis";
export function useLenis() {
useEffect(() => {
const lenis = new Lenis();
function raf(time: number) {
lenis.raf(time);
requestAnimationFrame(raf);
}
const id = requestAnimationFrame(raf);
return () => {
cancelAnimationFrame(id);
lenis.destroy();
};
}, []);
}
// In your root layout:
export default function Layout({ children }) {
useLenis();
return <>{children}</>;
}Integration with GSAP ScrollTrigger
import Lenis from "lenis";
import gsap from "gsap";
import ScrollTrigger from "gsap/ScrollTrigger";
gsap.registerPlugin(ScrollTrigger);
const lenis = new Lenis();
lenis.on("scroll", ScrollTrigger.update);
gsap.ticker.add((time) => {
lenis.raf(time * 1000);
});
gsap.ticker.lagSmoothing(0);Related packages
Unified TypeScript SDK for building AI-powered apps — switch between 20+ LLM providers without rewriting code.
animejsGeneral JSLightweight JavaScript animation library with a tiny footprint and a powerful, expressive API.
AOSGeneral JSAn easy-to-use library that makes elements fade, slide, or zoom into view as the user scrolls down your page.
archiverGeneral JSStreaming interface for generating ZIP and TAR archives in Node.js — create compressed archives programmatically from files, directories, and buffers.
@formkit/auto-animateGeneral JS> Add smooth transitions to any element with a single line — zero-config animations for adds, removes, and moves.