# Lenis Codebase Overview ## Core Purpose - Smooth scrolling library optimized for modern browsers - Originally designed for WebGL-DOM synchronization - Handles complex scroll animations and parallax effects ## Key Features - Smooth scroll interpolation (lerp) - Touch device support - Nested scroll handling - GSAP ScrollTrigger integration - Infinite scroll support - Horizontal/vertical scrolling - Event system (scroll, virtual-scroll) ## Technical Implementation - Uses requestAnimationFrame for smooth animations - Supports both native and smooth scrolling modes - Handles wheel, touch, and scroll events - Provides virtual scroll capabilities - Manages scroll prevention and locking - Supports custom easing functions ## Core Instance Options ```typescript { wrapper?: Window | HTMLElement // Scroll container (default: window) content?: HTMLElement // Content element (default: document.documentElement) lerp?: number // Linear interpolation value (default: 0.1) duration?: number // Scroll animation duration in seconds orientation?: 'vertical' | 'horizontal' // Scroll direction (default: 'vertical') gestureOrientation?: 'vertical' | 'horizontal' | 'both' smoothWheel?: boolean // Smooth wheel events (default: true) smoothTouch?: boolean // Smooth touch events (default: false) wheelMultiplier?: number // Wheel multiplication factor (default: 1) touchMultiplier?: number // Touch multiplication factor (default: 2) infinite?: boolean // Enable infinite scrolling (default: false) autoResize?: boolean // Auto resize on content changes (default: true) } ``` ## Key Methods ```typescript scrollTo(target: number | string | HTMLElement, options?: { offset?: number lerp?: number duration?: number immediate?: boolean lock?: boolean force?: boolean onComplete?: () => void }) stop() // Pause scrolling start() // Resume scrolling destroy() // Cleanup instance resize() // Recalculate dimensions setScroll(value) // Set scroll position isLocked() // Check if scrolling is locked isStopped() // Check if scrolling is stopped ``` ## Events ```typescript lenis.on('scroll', ({ scroll, limit, velocity, direction, progress }) => {}) lenis.on('virtual-scroll', ({ deltaX, deltaY, event }) => {}) ``` ## Architecture - Core Lenis class - Animate system - Dimensions handling - Event emitter - Virtual scroll implementation - TypeScript support ## Integration Methods - NPM package: `npm i lenis` - CDN: `` - CSS stylesheet: `import 'lenis/dist/lenis.css'` - Framework integrations (React, Vue) ## Common Usage Patterns ```typescript // Basic setup const lenis = new Lenis() function raf(time) { lenis.raf(time) requestAnimationFrame(raf) } requestAnimationFrame(raf) // GSAP integration lenis.on('scroll', ScrollTrigger.update) gsap.ticker.add((time) => lenis.raf(time * 1000)) gsap.ticker.lagSmoothing(0) // Nested scroll prevention const lenis = new Lenis({ prevent: (node) => node.classList.contains('scrollable') }) ``` ## Limitations - No native CSS scroll-snap support (use lenis/snap package) - Safari FPS caps: 60fps, 30fps in low power mode - iframe scroll limitations (no wheel event forwarding) - Safari pre-M1 fixed position lag - iOS < 16 touch event quirks with smoothTouch - Nested scroll requires proper configuration ## File Structure - /packages/core - Main implementation - /packages/react - React integration - /packages/vue - Vue integration - /packages/snap - Scroll snap support - lenis.css - Core styles - types.ts - TypeScript definitions ## Performance Considerations - RAF optimization - Touch event handling - Scroll synchronization - Browser compatibility - Device-specific behaviors ## Extension Points - Virtual scroll customization - Event system - Scroll prevention logic - Animation configuration - Framework integrations ## Packages ### Core Package (lenis) ```typescript // Basic usage import Lenis from 'lenis' const lenis = new Lenis({ duration: 1.2, easing: (t) => Math.min(1, 1.001 - Math.pow(2, -10 * t)), orientation: 'vertical', gestureOrientation: 'vertical', smoothWheel: true, wheelMultiplier: 1, smoothTouch: false, touchMultiplier: 2 }) // Required CSS html.lenis { height: auto; } .lenis.lenis-smooth { scroll-behavior: auto !important; } .lenis.lenis-smooth [data-lenis-prevent] { overscroll-behavior: contain; } .lenis.lenis-stopped { overflow: clip; } ``` ### React Package (lenis/react) ```typescript import { ReactLenis, useLenis } from 'lenis/react' // Component wrapper function App() { return ( {/* content */} ) } // Hook usage function Component() { const lenis = useLenis(({ scroll }) => { // Called every scroll }) return } // Custom RAF function CustomRaf() { const lenisRef = useRef() useEffect(() => { function raf(time) { lenisRef.current?.lenis?.raf(time) } requestAnimationFrame(raf) }, []) return ( {/* content */} ) } ``` ### Vue Package (lenis/vue) ```typescript import { VueLenis, useLenis } from 'lenis/vue' // Component usage // Composition API usage const lenis = useLenis(({ scroll }) => { // Called every scroll }) // Props interface LenisProps { root?: boolean // Setup global instance options?: LenisOptions // Lenis options autoRaf?: boolean // Auto RAF setup className?: string // Wrapper class } ``` ### Snap Package (lenis/snap) ```typescript import Lenis from 'lenis' import Snap from 'lenis/snap' const lenis = new Lenis() const snap = new Snap(lenis, { type: 'mandatory', // 'mandatory' | 'proximity' velocityThreshold: 1, // Snap velocity threshold snapToChildren: true, // Snap to direct children snapChildren: '.snap-target', // CSS selector for snap targets duration: 1, // Snap animation duration easing: (t) => t, // Snap easing function onSnapStart: (snap) => {}, // Snap start callback onSnapComplete: (snap) => {} // Snap complete callback }) // Manual snap points snap.add(500) // Snap at 500px snap.add(1000) // Snap at 1000px // Element-based snapping snap.addElement(element, { align: ['start', 'center', 'end'] }) ``` ## Package-specific Features ### Core - Base scrolling functionality - Virtual scroll system - Event handling - Dimension management - Animation system ### React - React component wrapper - useLenis hook - Automatic cleanup - Context system - Ref forwarding - TypeScript support ### Vue - Vue component wrapper - useLenis composable - Auto RAF management - Props validation - Template integration - TypeScript support ### Snap - CSS scroll-snap alternative - Element-based snapping - Manual snap points - Velocity-based snapping - Animation customization ## Package Integration Patterns ### Core + GSAP ```typescript lenis.on('scroll', ScrollTrigger.update) gsap.ticker.add((time) => lenis.raf(time * 1000)) gsap.ticker.lagSmoothing(0) ``` ### React + Snap ```typescript function App() { const lenisRef = useRef() useEffect(() => { const snap = new Snap(lenisRef.current.lenis, { type: 'mandatory' }) return () => snap.destroy() }, []) return {/* content */} } ``` ### Vue + Custom RAF ```typescript ```