locomotive-scroll

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Locomotive 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-scroll
javascript
// 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-scroll
javascript
// 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属性

AttributePurposeExample
data-scroll
Enable detection
data-scroll
data-scroll-speed
Parallax speed
data-scroll-speed="2"
data-scroll-direction
Parallax axis
data-scroll-direction="horizontal"
data-scroll-sticky
Sticky positioning
data-scroll-sticky
data-scroll-target
Sticky boundary
data-scroll-target="#section"
data-scroll-offset
Trigger offset
data-scroll-offset="20%"
data-scroll-repeat
Repeat detection
data-scroll-repeat
data-scroll-call
Event trigger
data-scroll-call="myFunction"
data-scroll-id
Unique identifier
data-scroll-id="hero"
data-scroll-class
Custom class
data-scroll-class="is-visible"
属性用途示例
data-scroll
启用元素检测
data-scroll
data-scroll-speed
视差速度
data-scroll-speed="2"
data-scroll-direction
视差轴方向
data-scroll-direction="horizontal"
data-scroll-sticky
粘性定位
data-scroll-sticky
data-scroll-target
粘性边界
data-scroll-target="#section"
data-scroll-offset
触发偏移量
data-scroll-offset="20%"
data-scroll-repeat
重复检测
data-scroll-repeat
data-scroll-call
事件触发
data-scroll-call="myFunction"
data-scroll-id
唯一标识符
data-scroll-id="hero"
data-scroll-class
自定义类名
data-scroll-class="is-visible"

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

性能优化

  1. Use
    data-scroll-section
    to segment long pages:
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>
  1. Limit parallax elements - Too many can impact performance
  2. Disable on mobile if performance is poor:
javascript
smartphone: { smooth: false }
  1. Update on resize:
javascript
window.addEventListener('resize', () => {
  scroll.update();
});
  1. Destroy when not needed:
javascript
scroll.destroy();
  1. **使用
    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>
  1. 限制视差元素数量 - 过多视差元素会影响性能
  2. 移动端禁用平滑滚动(如果性能不佳):
javascript
smartphone: { smooth: false }
  1. 窗口大小改变时更新
javascript
window.addEventListener('resize', () => {
  scroll.update();
});
  1. 不需要时销毁实例
javascript
scroll.destroy();

Common Pitfalls

常见问题与解决方法

1. Fixed Positioning Issues

1. 固定定位问题

Problem:
position: fixed
elements break with smooth scroll
Solution: Use
data-scroll-sticky
instead or add fixed elements outside container:
html
<!-- Fixed nav outside container -->
<nav style="position: fixed;">Navigation</nav>

<div data-scroll-container>
  <!-- Page content -->
</div>
问题
position: fixed
元素在平滑滚动下失效
解决方案:改用
data-scroll-sticky
,或把固定元素放在滚动容器外:
html
<!-- 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
update()
after DOM changes:
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:
    generate_config.py
    - Configuration generator,
    integration_helper.py
    - GSAP integration code
  • References:
    api_reference.md
    - Complete API,
    gsap_integration.md
    - GSAP ScrollTrigger patterns
  • Assets:
    starter_locomotive/
    - Complete starter template with examples
  • 脚本
    generate_config.py
    - 配置生成器,
    integration_helper.py
    - GSAP集成代码
  • 参考文档
    api_reference.md
    - 完整API文档,
    gsap_integration.md
    - GSAP ScrollTrigger使用模式
  • 资源包
    starter_locomotive/
    - 包含示例的完整入门模板