Skip to content

14islands/lenis

 
 

Repository files navigation

LENIS

Introduction

🚧 Still in WIP, API might change with new releases 🚧

This is our take on smooth scroll, lightweight, hard working, smooth as butter scroll. See Demo


Features

  • Performant
  • Lightweight (~2Kb gzipped)
  • Run scroll in main thread
  • Accessibility (CMD+F page search, keyboard navigation, keep scroll position on page refresh, etc.)
  • External RAF
  • SSR proof
  • Not opinionated
  • Tree-shakeable
  • Custom scroll easing/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.33KB 26.08KB 2.13kb

Installing

using package manager:

$ npm i @studio-freight/lenis

using scripts:

<script src="https://cdn.jsdelivr.net/gh/studio-freight/lenis@latest/bundled/lenis.js"></script>

Setup

Basic setup

import Lenis from '@studio-freight/lenis'

const lenis = new Lenis({
  duration: 1.2,
  easing: (t) => (t === 1 ? 1 : 1 - Math.pow(2, -10 * t)), // https://easings.net/en#easeOutExpo
  direction: 'vertical', // vertical, horizontal
  gestureDirection: 'vertical', // vertical, horizontal, both
  smooth: true,
  smoothTouch: false,
  touchMultiplier: 2,
})

//get scroll value
lenis.on('scroll', ({ scroll, limit, velocity, direction, progress }) => {
  console.log({ scroll, limit, velocity, direction, progress })
})

function raf(time) {
  lenis.raf(time)
  requestAnimationFrame(raf)
}

requestAnimationFrame(raf)

Using custom scroll container

const lenis = new Lenis({
  wrapper: NodeElement, // element that has overflow
  content: NodeElement, // usually wrapper's direct child
  duration: 1.2,
  easing: (t) => (t === 1 ? 1 : 1 - Math.pow(2, -10 * t)),
  direction: 'vertical',
  gestureDirection: 'vertical',
  smooth: true,
  smoothTouch: false,
  touchMultiplier: 2,
})

Methods

  • raf(time) : must be called every frame for internal function.
  • scrollTo(target, {offset, duration, easing, immediate}) : scroll to a target.
    • target : can be Number, NodeElement or String (CSS selector).
    • offset : Number equivalent to scroll-padding-top.
    • duration : Number scroll duration in seconds.
    • easing : Function.
    • immediate : ignore duration and easing.
  • on(id, callback) : execute a function on event.
    • id : event to listen.
      • scroll : return scroll position.
    • callback(e) : function to execute.
  • stop() : pause the scroll
  • start() : resume the scroll
  • destroy() : destroy the instance, remove all events.

Considerations

Things to consider if you want to add Lenis to your codebase will be listed here.

Make sure scroll-behavior is set to initial or not set at all (thanks @thagxt)

html {
  scroll-behavior: initial;
}

Keep html and body elements default sized (see this issue)

html,
body {
  width: 100%;
  min-height: 100%;
}

Stop wheel event propagation on elements with overflow (see this issue)

<div onwheel="event.stopPropagation()">scroll content</div>

Manually use lenis.scrollTo('#anchor') on anchor link click (see this issue)

<a href="#anchor" onclick="lenis.scrollTo('#anchor')">scroll to anchor</a>

Plugins


Lenis in use


Authors

This set of hooks is curated and maintained by the Studio Freight Darkroom team:


License

The MIT License.

Releases

No releases published

Packages

No packages published

Languages

  • JavaScript 76.9%
  • SCSS 22.0%
  • GLSL 1.1%