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