Lenis Smooth Scroll Library

repository·main·Indexed 12 days ago

https://github.com/darkroomengineering/lenis

A lightweight, high-performance smooth scroll library (v1.3.26) that wraps the browser's native scroll. It maintains compatibility with sticky positioning and accessibility while supporting WebGL, parallax, and GSAP animations. Includes official integrations for React, Vue, and Nuxt, as well as a snapping extension via lenis/snap.

Tokens
17.5K
Snippets
65
Records
83
Agent score
96%

What's inside Lenis

  1. New features in Lenis v2

    main

    Lenis v2 introduces several improvements for a more seamless developer experience and expanded capabilities:

    • Auto CSS injection: Critical styles are injected at runtime, removing the need to manually import lenis.css.
    • Pull to refresh & UI collapse: Support for native browser behaviors when touch.smooth is enabled.
    • Multi-axis scrolling: Support for simultaneous X and Y scrolling (e.g., for 2D canvas navigation or spreadsheets).
    • Development Warnings: Warnings in development mode when calling infinite on html/body to prevent iOS flickering.
  2. Handle user prefers-reduced-motion settings

    main

    Lenis automatically honors the browser's prefers-reduced-motion setting. When a user has this enabled:

    • Smoothing is disabled (lerp is forced to 1).
    • The scroll tracks the input device 1:1.
    • Programmatic scrolls (scrollTo, anchor links) jump instantly to the target.
    • Lenis continues to run to maintain WebGL/DOM synchronization.

    You can check lenis.prefersReducedMotion to adapt your own animations. To opt out of this behavior (not recommended), set respectReducedMotion: false.

    const lenis = new Lenis({
      respectReducedMotion: false,
    })
  3. How <ReactLenis> and useLenis work together

    main

    The lenis/react package uses a Provider pattern. The <ReactLenis> component creates a Lenis instance and provides it to its children via React Context. This allows any child component to access the Lenis instance using the useLenis hook without manual prop drilling.

    To make Lenis globally accessible (using the default <html> scroll container), use the root prop on <ReactLenis>.

    import { ReactLenis, useLenis } from 'lenis/react'
    
    function App() {
      // useLenis can be used inside components wrapped by <ReactLenis />
      const lenis = useLenis((lenis) => {
        // called every scroll
        console.log(lenis)
      })
    
      return (
        <ReactLenis root />
        { /* content */ }
      )
    }
  4. Handle nested scrollable elements

    main

    To allow nested elements (like modals or sidebars) to scroll natively without interfering with the main Lenis smooth scroll, you have two primary methods:

    1. Automatic Detection: Use the allowNestedScroll: true option. This is the simplest method but may impact performance as Lenis must check the DOM tree during scroll events.
    2. Manual Prevention (Recommended for performance): Use HTML data-lenis-prevent attributes or a JavaScript predicate to tell Lenis which elements should ignore smooth scroll events.

    If you experience performance issues with allowNestedScroll, switch to using HTML attributes or the prevent option.

    // Method 1: Automatic detection
    const lenis = new Lenis({
      allowNestedScroll: true,
    })
    
    // Method 2: JavaScript predicate
    const lenis = new Lenis({
      prevent: (node) => node.id === 'modal',
    })
  5. Install lenis/vue

    main

    To use Lenis in a Vue project, install the lenis package via npm.

    Vue Setup

    Register the vueLenisPlugin globally in your main.js to use the <vue-lenis> component in your templates without manual imports.

    Nuxt Setup

    Add lenis/nuxt to your modules array in nuxt.config.js.

    npm i lenis
    // main.js
    import { createApp } from 'vue'
    import LenisVue from 'lenis/vue'
    
    const app = createApp({})
    
    app.use(LenisVue)
    // nuxt.config.js
    export default defineNuxtConfig({
      modules: ['lenis/nuxt'],
    })
  6. Integrate Lenis with GSAP ScrollTrigger

    main

    To synchronize Lenis smooth scrolling with GSAP's ScrollTrigger, you must update ScrollTrigger on every Lenis scroll event and add Lenis's raf method to the GSAP ticker. It is also recommended to disable GSAP's lag smoothing to prevent delays.

    // 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);
    // 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);
  7. Build and preview the Nuxt Minimal Starter for production

    main

    To prepare the application for production, build the project and then use the preview command to test the production build locally.

    # Build for production
    # npm
    npm run build
    
    # pnpm
    pnpm build
    
    # yarn
    yarn build
    
    # bun
    bun run build
    
    # Preview production build locally
    # npm
    npm run preview
    
    # pnpm
    pnpm preview
    
    # yarn
    yarn preview
    
    # bun
    bun run preview
  8. No-code Usage (CDN)

    main

    For a quick implementation without a build step, drop the CSS and JS into your HTML and initialize Lenis with a comprehensive configuration object to handle common edge cases like modals, anchors, and nested scrolling.

    <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>
    <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>