locomotive-scroll
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseLocomotive Scroll
Locomotive Scroll
Comprehensive guide for implementing smooth scrolling, parallax effects, and scroll-driven animations using Locomotive Scroll.
本指南全面介绍如何使用Locomotive Scroll实现平滑滚动、视差效果和滚动驱动动画。
Overview
概述
Locomotive Scroll is a JavaScript library that provides:
- Smooth scrolling: Hardware-accelerated smooth scroll with customizable easing
- Parallax effects: Element-level speed control for depth
- Viewport detection: Track when elements enter/exit viewport
- Scroll events: Monitor scroll progress for animation synchronization
- Sticky elements: Pin elements within defined boundaries
- Horizontal scrolling: Support for horizontal scroll layouts
When to use Locomotive Scroll:
- Building immersive landing pages with parallax
- Creating smooth, Apple-style scroll experiences
- Implementing scroll-triggered animations
- Developing narrative/storytelling websites
- Adding depth and motion to long-form content
Trade-offs:
- Scroll-hijacking can impact accessibility (provide disable option)
- Performance overhead on low-end devices (detect and disable)
- Mobile touch scrolling feels different (test extensively)
- Fixed positioning requires workarounds
Locomotive Scroll是一款JavaScript库,提供以下功能:
- 平滑滚动:硬件加速的平滑滚动,支持自定义缓动效果
- 视差效果:支持元素级别的速度控制,营造深度感
- 视口检测:追踪元素进入/离开视口的时机
- 滚动事件:监控滚动进度,实现动画同步
- 粘性元素:在指定边界内固定元素
- 横向滚动:支持横向滚动布局
何时使用Locomotive Scroll:
- 构建带有视差效果的沉浸式着陆页
- 打造类似苹果风格的平滑滚动体验
- 实现滚动触发式动画
- 开发叙事类/故事型网站
- 为长内容增添深度和动态效果
注意事项:
- 滚动劫持可能影响可访问性(需提供禁用选项)
- 在低端设备上会有性能损耗(建议检测并禁用)
- 移动端触摸滚动体验与原生不同(需充分测试)
- 固定定位需要特殊处理
Installation
安装
bash
npm install locomotive-scrolljavascript
// ES6
import LocomotiveScroll from 'locomotive-scroll';
import 'locomotive-scroll/dist/locomotive-scroll.css';
// Or via CDN
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/locomotive-scroll/dist/locomotive-scroll.min.css">
<script src="https://cdn.jsdelivr.net/npm/locomotive-scroll/dist/locomotive-scroll.min.js"></script>bash
npm install locomotive-scrolljavascript
// ES6
import LocomotiveScroll from 'locomotive-scroll';
import 'locomotive-scroll/dist/locomotive-scroll.css';
// Or via CDN
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/locomotive-scroll/dist/locomotive-scroll.min.css">
<script src="https://cdn.jsdelivr.net/npm/locomotive-scroll/dist/locomotive-scroll.min.js"></script>Core Concepts
核心概念
1. HTML Structure
1. HTML结构
Every Locomotive Scroll implementation requires specific data attributes:
html
<!-- Scroll container (required) -->
<div data-scroll-container>
<!-- Scroll sections (optional, improves performance) -->
<div data-scroll-section>
<!-- Tracked elements -->
<h1 data-scroll>Basic detection</h1>
<!-- Parallax element -->
<div data-scroll data-scroll-speed="2">
Moves faster than scroll
</div>
<!-- Sticky element -->
<div data-scroll data-scroll-sticky>
Sticks within section
</div>
<!-- Element with ID for tracking -->
<div data-scroll data-scroll-id="hero">
Accessible via JavaScript
</div>
<!-- Call event trigger -->
<div data-scroll data-scroll-call="fadeIn">
Triggers custom event
</div>
</div>
</div>每个Locomotive Scroll实现都需要特定的data属性:
html
<!-- Scroll container (required) -->
<div data-scroll-container>
<!-- Scroll sections (optional, improves performance) -->
<div data-scroll-section>
<!-- Tracked elements -->
<h1 data-scroll>Basic detection</h1>
<!-- Parallax element -->
<div data-scroll data-scroll-speed="2">
Moves faster than scroll
</div>
<!-- Sticky element -->
<div data-scroll data-scroll-sticky>
Sticks within section
</div>
<!-- Element with ID for tracking -->
<div data-scroll data-scroll-id="hero">
Accessible via JavaScript
</div>
<!-- Call event trigger -->
<div data-scroll data-scroll-call="fadeIn">
Triggers custom event
</div>
</div>
</div>2. Initialization
2. 初始化
javascript
const scroll = new LocomotiveScroll({
el: document.querySelector('[data-scroll-container]'),
smooth: true,
lerp: 0.1, // Smoothness (0-1, lower = smoother)
multiplier: 1, // Speed multiplier
class: 'is-inview', // Class added to visible elements
repeat: false, // Repeat in-view detection
offset: [0, 0] // Global trigger offset [bottom, top]
});javascript
const scroll = new LocomotiveScroll({
el: document.querySelector('[data-scroll-container]'),
smooth: true,
lerp: 0.1, // Smoothness (0-1, lower = smoother)
multiplier: 1, // Speed multiplier
class: 'is-inview', // Class added to visible elements
repeat: false, // Repeat in-view detection
offset: [0, 0] // Global trigger offset [bottom, top]
});3. Data Attributes
3. Data属性
| Attribute | Purpose | Example |
|---|---|---|
| Enable detection | |
| Parallax speed | |
| Parallax axis | |
| Sticky positioning | |
| Sticky boundary | |
| Trigger offset | |
| Repeat detection | |
| Event trigger | |
| Unique identifier | |
| Custom class | |
| 属性 | 用途 | 示例 |
|---|---|---|
| 启用元素检测 | |
| 视差速度 | |
| 视差轴方向 | |
| 粘性定位 | |
| 粘性边界 | |
| 触发偏移量 | |
| 重复检测 | |
| 事件触发 | |
| 唯一标识符 | |
| 自定义类名 | |
Common Patterns
常见使用模式
1. Basic Smooth Scrolling
1. 基础平滑滚动
javascript
import LocomotiveScroll from 'locomotive-scroll';
const scroll = new LocomotiveScroll({
el: document.querySelector('[data-scroll-container]'),
smooth: true
});html
<div data-scroll-container>
<div data-scroll-section>
<h1>Smooth scrolling enabled</h1>
</div>
</div>javascript
import LocomotiveScroll from 'locomotive-scroll';
const scroll = new LocomotiveScroll({
el: document.querySelector('[data-scroll-container]'),
smooth: true
});html
<div data-scroll-container>
<div data-scroll-section>
<h1>Smooth scrolling enabled</h1>
</div>
</div>2. Parallax Effects
2. 视差效果
html
<!-- Slow parallax -->
<div data-scroll data-scroll-speed="0.5">
Moves slower than scroll (background effect)
</div>
<!-- Fast parallax -->
<div data-scroll data-scroll-speed="3">
Moves faster than scroll (foreground effect)
</div>
<!-- Reverse parallax -->
<div data-scroll data-scroll-speed="-2">
Moves in opposite direction
</div>
<!-- Horizontal parallax -->
<div data-scroll data-scroll-speed="2" data-scroll-direction="horizontal">
Moves horizontally
</div>html
<!-- Slow parallax -->
<div data-scroll data-scroll-speed="0.5">
Moves slower than scroll (background effect)
</div>
<!-- Fast parallax -->
<div data-scroll data-scroll-speed="3">
Moves faster than scroll (foreground effect)
</div>
<!-- Reverse parallax -->
<div data-scroll data-scroll-speed="-2">
Moves in opposite direction
</div>
<!-- Horizontal parallax -->
<div data-scroll data-scroll-speed="2" data-scroll-direction="horizontal">
Moves horizontally
</div>3. Viewport Detection and Callbacks
3. 视口检测与回调
javascript
// Track scroll progress
scroll.on('scroll', (args) => {
console.log(args.scroll.y); // Current scroll position
console.log(args.speed); // Scroll speed
console.log(args.direction); // Scroll direction
// Access specific element progress
if (args.currentElements['hero']) {
const progress = args.currentElements['hero'].progress;
console.log(`Hero progress: ${progress}`); // 0 to 1
}
});
// Call events
scroll.on('call', (value, way, obj) => {
console.log(`Event triggered: ${value}`);
// value = data-scroll-call attribute value
// way = 'enter' or 'exit'
// obj = {id, el}
});html
<div data-scroll data-scroll-id="hero">Hero section</div>
<div data-scroll data-scroll-call="playVideo">Video section</div>javascript
// Track scroll progress
scroll.on('scroll', (args) => {
console.log(args.scroll.y); // Current scroll position
console.log(args.speed); // Scroll speed
console.log(args.direction); // Scroll direction
// Access specific element progress
if (args.currentElements['hero']) {
const progress = args.currentElements['hero'].progress;
console.log(`Hero progress: ${progress}`); // 0 to 1
}
});
// Call events
scroll.on('call', (value, way, obj) => {
console.log(`Event triggered: ${value}`);
// value = data-scroll-call attribute value
// way = 'enter' or 'exit'
// obj = {id, el}
});html
<div data-scroll data-scroll-id="hero">Hero section</div>
<div data-scroll data-scroll-call="playVideo">Video section</div>4. Sticky Elements
4. 粘性元素
html
<!-- Stick within parent section -->
<div data-scroll-section>
<div data-scroll data-scroll-sticky>
I stick while section is in view
</div>
</div>
<!-- Stick with specific target -->
<div id="sticky-container">
<div data-scroll data-scroll-sticky data-scroll-target="#sticky-container">
I stick within #sticky-container
</div>
</div>html
<!-- Stick within parent section -->
<div data-scroll-section>
<div data-scroll data-scroll-sticky>
I stick while section is in view
</div>
</div>
<!-- Stick with specific target -->
<div id="sticky-container">
<div data-scroll data-scroll-sticky data-scroll-target="#sticky-container">
I stick within #sticky-container
</div>
</div>5. Programmatic Scrolling
5. 程序化滚动
javascript
// Scroll to element
scroll.scrollTo('#target-section');
// Scroll to top
scroll.scrollTo('top');
// Scroll to bottom
scroll.scrollTo('bottom');
// Scroll with options
scroll.scrollTo('#target', {
offset: -100, // Offset in pixels
duration: 1000, // Duration in ms
easing: [0.25, 0.0, 0.35, 1.0], // Cubic bezier
disableLerp: true, // Disable smooth lerp
callback: () => console.log('Scrolled!')
});
// Scroll to pixel value
scroll.scrollTo(500);javascript
// Scroll to element
scroll.scrollTo('#target-section');
// Scroll to top
scroll.scrollTo('top');
// Scroll to bottom
scroll.scrollTo('bottom');
// Scroll with options
scroll.scrollTo('#target', {
offset: -100, // Offset in pixels
duration: 1000, // Duration in ms
easing: [0.25, 0.0, 0.35, 1.0], // Cubic bezier
disableLerp: true, // Disable smooth lerp
callback: () => console.log('Scrolled!')
});
// Scroll to pixel value
scroll.scrollTo(500);6. Horizontal Scrolling
6. 横向滚动
javascript
const scroll = new LocomotiveScroll({
el: document.querySelector('[data-scroll-container]'),
smooth: true,
direction: 'horizontal'
});html
<div data-scroll-container>
<div data-scroll-section style="display: flex; width: 300vw;">
<div>Section 1</div>
<div>Section 2</div>
<div>Section 3</div>
</div>
</div>javascript
const scroll = new LocomotiveScroll({
el: document.querySelector('[data-scroll-container]'),
smooth: true,
direction: 'horizontal'
});html
<div data-scroll-container>
<div data-scroll-section style="display: flex; width: 300vw;">
<div>Section 1</div>
<div>Section 2</div>
<div>Section 3</div>
</div>
</div>7. Mobile Responsiveness
7. 移动端响应式
javascript
const scroll = new LocomotiveScroll({
el: document.querySelector('[data-scroll-container]'),
smooth: true,
// Tablet settings
tablet: {
smooth: true,
breakpoint: 1024
},
// Smartphone settings
smartphone: {
smooth: false, // Disable on mobile for performance
breakpoint: 768
}
});javascript
const scroll = new LocomotiveScroll({
el: document.querySelector('[data-scroll-container]'),
smooth: true,
// Tablet settings
tablet: {
smooth: true,
breakpoint: 1024
},
// Smartphone settings
smartphone: {
smooth: false, // Disable on mobile for performance
breakpoint: 768
}
});Integration with GSAP ScrollTrigger
与GSAP ScrollTrigger集成
Locomotive Scroll and GSAP ScrollTrigger work together for advanced animations:
javascript
import LocomotiveScroll from 'locomotive-scroll';
import { gsap } from 'gsap';
import { ScrollTrigger } from 'gsap/ScrollTrigger';
gsap.registerPlugin(ScrollTrigger);
const locoScroll = new LocomotiveScroll({
el: document.querySelector('[data-scroll-container]'),
smooth: true
});
// Sync Locomotive Scroll with ScrollTrigger
locoScroll.on('scroll', ScrollTrigger.update);
ScrollTrigger.scrollerProxy('[data-scroll-container]', {
scrollTop(value) {
return arguments.length
? locoScroll.scrollTo(value, 0, 0)
: locoScroll.scroll.instance.scroll.y;
},
getBoundingClientRect() {
return {
top: 0,
left: 0,
width: window.innerWidth,
height: window.innerHeight
};
},
pinType: document.querySelector('[data-scroll-container]').style.transform
? 'transform'
: 'fixed'
});
// GSAP animation with ScrollTrigger
gsap.to('.fade-in', {
scrollTrigger: {
trigger: '.fade-in',
scroller: '[data-scroll-container]',
start: 'top bottom',
end: 'top center',
scrub: true
},
opacity: 1,
y: 0
});
// Update ScrollTrigger when Locomotive updates
ScrollTrigger.addEventListener('refresh', () => locoScroll.update());
ScrollTrigger.refresh();Locomotive Scroll和GSAP ScrollTrigger可配合使用,实现高级动画:
javascript
import LocomotiveScroll from 'locomotive-scroll';
import { gsap } from 'gsap';
import { ScrollTrigger } from 'gsap/ScrollTrigger';
gsap.registerPlugin(ScrollTrigger);
const locoScroll = new LocomotiveScroll({
el: document.querySelector('[data-scroll-container]'),
smooth: true
});
// Sync Locomotive Scroll with ScrollTrigger
locoScroll.on('scroll', ScrollTrigger.update);
ScrollTrigger.scrollerProxy('[data-scroll-container]', {
scrollTop(value) {
return arguments.length
? locoScroll.scrollTo(value, 0, 0)
: locoScroll.scroll.instance.scroll.y;
},
getBoundingClientRect() {
return {
top: 0,
left: 0,
width: window.innerWidth,
height: window.innerHeight
};
},
pinType: document.querySelector('[data-scroll-container]').style.transform
? 'transform'
: 'fixed'
});
// GSAP animation with ScrollTrigger
gsap.to('.fade-in', {
scrollTrigger: {
trigger: '.fade-in',
scroller: '[data-scroll-container]',
start: 'top bottom',
end: 'top center',
scrub: true
},
opacity: 1,
y: 0
});
// Update ScrollTrigger when Locomotive updates
ScrollTrigger.addEventListener('refresh', () => locoScroll.update());
ScrollTrigger.refresh();Instance Methods
实例方法
javascript
const scroll = new LocomotiveScroll();
// Lifecycle
scroll.init(); // Reinitialize
scroll.update(); // Refresh element positions
scroll.destroy(); // Clean up
scroll.start(); // Resume scrolling
scroll.stop(); // Pause scrolling
// Navigation
scroll.scrollTo(target, options);
scroll.setScroll(x, y);
// Events
scroll.on('scroll', callback);
scroll.on('call', callback);
scroll.off('scroll', callback);javascript
const scroll = new LocomotiveScroll();
// Lifecycle
scroll.init(); // Reinitialize
scroll.update(); // Refresh element positions
scroll.destroy(); // Clean up
scroll.start(); // Resume scrolling
scroll.stop(); // Pause scrolling
// Navigation
scroll.scrollTo(target, options);
scroll.setScroll(x, y);
// Events
scroll.on('scroll', callback);
scroll.on('call', callback);
scroll.off('scroll', callback);Performance Optimization
性能优化
- Use to segment long pages:
data-scroll-section
html
<div data-scroll-container>
<div data-scroll-section>Section 1</div>
<div data-scroll-section>Section 2</div>
<div data-scroll-section>Section 3</div>
</div>-
Limit parallax elements - Too many can impact performance
-
Disable on mobile if performance is poor:
javascript
smartphone: { smooth: false }- Update on resize:
javascript
window.addEventListener('resize', () => {
scroll.update();
});- Destroy when not needed:
javascript
scroll.destroy();- **使用**分割长页面:
data-scroll-section
html
<div data-scroll-container>
<div data-scroll-section>Section 1</div>
<div data-scroll-section>Section 2</div>
<div data-scroll-section>Section 3</div>
</div>-
限制视差元素数量 - 过多视差元素会影响性能
-
移动端禁用平滑滚动(如果性能不佳):
javascript
smartphone: { smooth: false }- 窗口大小改变时更新:
javascript
window.addEventListener('resize', () => {
scroll.update();
});- 不需要时销毁实例:
javascript
scroll.destroy();Common Pitfalls
常见问题与解决方法
1. Fixed Positioning Issues
1. 固定定位问题
Problem: elements break with smooth scroll
position: fixedSolution: Use instead or add fixed elements outside container:
data-scroll-stickyhtml
<!-- Fixed nav outside container -->
<nav style="position: fixed;">Navigation</nav>
<div data-scroll-container>
<!-- Page content -->
</div>问题:元素在平滑滚动下失效
position: fixed解决方案:改用,或把固定元素放在滚动容器外:
data-scroll-stickyhtml
<!-- Fixed nav outside container -->
<nav style="position: fixed;">Navigation</nav>
<div data-scroll-container>
<!-- Page content -->
</div>2. Images Not Lazy Loading
2. 图片懒加载失效
Problem: All images load at once
Solution: Integrate with lazy loading:
html
<img data-scroll data-src="image.jpg" class="lazy">javascript
scroll.on('call', (func) => {
if (func === 'lazyLoad') {
// Trigger lazy load
}
});问题:所有图片一次性加载
解决方案:集成懒加载:
html
<img data-scroll data-src="image.jpg" class="lazy">javascript
scroll.on('call', (func) => {
if (func === 'lazyLoad') {
// Trigger lazy load
}
});3. Scroll Position Not Updating
3. 滚动位置不更新
Problem: Dynamic content doesn't update scroll positions
Solution: Call after DOM changes:
update()javascript
// After adding content
addDynamicContent();
scroll.update();问题:动态内容无法更新滚动位置
解决方案:DOM变更后调用:
update()javascript
// After adding content
addDynamicContent();
scroll.update();4. Accessibility Concerns
4. 可访问性问题
Problem: Screen readers and keyboard navigation broken
Solution: Provide disable option:
javascript
const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
const scroll = new LocomotiveScroll({
smooth: !prefersReducedMotion
});问题:屏幕阅读器和键盘导航失效
解决方案:提供禁用选项:
javascript
const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
const scroll = new LocomotiveScroll({
smooth: !prefersReducedMotion
});5. Memory Leaks
5. 内存泄漏
Problem: Scroll instance not cleaned up on route changes (SPAs)
Solution: Always destroy on unmount:
javascript
// React example
useEffect(() => {
const scroll = new LocomotiveScroll();
return () => scroll.destroy();
}, []);问题:单页应用路由切换时未清理滚动实例
解决方案:卸载时务必销毁实例:
javascript
// React example
useEffect(() => {
const scroll = new LocomotiveScroll();
return () => scroll.destroy();
}, []);6. Z-Index Fighting
6. Z轴层级冲突
Problem: Parallax elements overlap incorrectly
Solution: Set explicit z-index on parallax layers:
css
[data-scroll-speed] {
position: relative;
z-index: var(--layer-depth);
}问题:视差元素重叠错误
解决方案:为视差层设置明确的z-index:
css
[data-scroll-speed] {
position: relative;
z-index: var(--layer-depth);
}Related Skills
相关技能
- gsap-scrolltrigger: Advanced scroll-driven animations (use together)
- barba-js: Page transitions with Locomotive Scroll integration
- scroll-reveal-libraries: Simpler alternative for basic fade-in effects
- react-three-fiber: Scroll-driven 3D scenes (sync with Locomotive events)
- motion-framer: Alternative scroll animations in React
- gsap-scrolltrigger:高级滚动驱动动画(建议配合使用)
- barba-js:支持Locomotive Scroll集成的页面过渡库
- scroll-reveal-libraries:基础淡入效果的简易替代方案
- react-three-fiber:滚动驱动的3D场景(可与Locomotive事件同步)
- motion-framer:React中替代滚动动画的方案
Resources
资源
- Scripts: - Configuration generator,
generate_config.py- GSAP integration codeintegration_helper.py - References: - Complete API,
api_reference.md- GSAP ScrollTrigger patternsgsap_integration.md - Assets: - Complete starter template with examples
starter_locomotive/
- 脚本:- 配置生成器,
generate_config.py- GSAP集成代码integration_helper.py - 参考文档:- 完整API文档,
api_reference.md- GSAP ScrollTrigger使用模式gsap_integration.md - 资源包:- 包含示例的完整入门模板
starter_locomotive/