locomotive-scroll について
locomotive-scrollは、スクロールを軸にしたWebサイトを作る開発者向けのJavaScriptライブラリです。スムーズスクロールに加え、視差、ビューポート検出、固定要素、横スクロールに対応します。
主な機能
- 01調整可能なスムーズスクロール
- 02要素単位の視差効果
- 03ビューポート検出とスクロールイベント
- 04固定要素と横スクロール
- 05プログラムによるスクロール
活用シーン
- 01ランディングページへの視差追加
- 02スクロール進捗とアニメーションの同期
- 03スクロール型のストーリーサイト制作
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ freshtechbro/ claudedesignskills --skill locomotive-scrollインストール後、Claude Code で/locomotive-scrollを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
assets/starter_locomotive/index.htmlmain.jspackage.jsonREADME.mdstyle.cssreferences/api_reference.mdgsap_integration.mdscripts/generate_config.pyintegration_helper.py詳細
Locomotive Scroll
Locomotive Scroll を使用して、スムーズスクロール、視差効果、スクロール駆動アニメーションを実装するための包括的なガイドです。
概要
Locomotive Scroll は、次の機能を提供する JavaScript ライブラリです。
- スムーズスクロール:カスタマイズ可能なイージングを備えた、ハードウェアアクセラレーション対応のスムーズスクロール
- 視差効果:奥行きを表現するための、要素単位の速度制御
- ビューポート検出:要素がビューポートに入る/出るタイミングを追跡
- スクロールイベント:アニメーションとの同期に使用するスクロールの進行状況を監視
- スティッキー要素:定義された境界内で要素を固定
- 横スクロール:横スクロールレイアウトに対応
Locomotive Scroll を使用する場面:
- 視差効果のある没入感の高いランディングページの構築
- Apple 風のスムーズなスクロール体験の作成
- スクロールに連動するアニメーションの実装
- ナラティブ/ストーリーテリング形式のウェブサイトの開発
- 長文コンテンツへの奥行きと動きの追加
トレードオフ:
- スクロールの乗っ取りはアクセシビリティに影響する可能性があります(無効化オプションを用意してください)
- ローエンドデバイスではパフォーマンスのオーバーヘッドが発生します(検出して無効化してください)
- モバイルのタッチスクロールは操作感が異なります(十分にテストしてください)
- 固定配置には回避策が必要です
インストール
npm install locomotive-scroll
// 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>
主な概念
1. HTML 構造
Locomotive Scroll を実装するには、特定のデータ属性が必要です。
<div data-scroll-container>
<div data-scroll-section>
<h1 data-scroll>Basic detection</h1>
<div data-scroll data-scroll-speed="2">
Moves faster than scroll
</div>
<div data-scroll data-scroll-sticky>
Sticks within section
</div>
<div data-scroll data-scroll-id="hero">
Accessible via JavaScript
</div>
<div data-scroll data-scroll-call="fadeIn">
Triggers custom event
</div>
</div>
</div>
2. 初期化
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-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" |
よくあるパターン
1. 基本的なスムーズスクロール
import LocomotiveScroll from 'locomotive-scroll';
const scroll = new LocomotiveScroll({
el: document.querySelector('[data-scroll-container]'),
smooth: true
});
<div data-scroll-container>
<div data-scroll-section>
<h1>Smooth scrolling enabled</h1>
</div>
</div>
2. 視差効果
<div data-scroll data-scroll-speed="0.5">
Moves slower than scroll (background effect)
</div>
<div data-scroll data-scroll-speed="3">
Moves faster than scroll (foreground effect)
</div>
<div data-scroll data-scroll-speed="-2">
Moves in opposite direction
</div>
<div data-scroll data-scroll-speed="2" data-scroll-direction="horizontal">
Moves horizontally
</div>
3. ビューポート検出とコールバック
// 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}
});
<div data-scroll data-scroll-id="hero">Hero section</div>
<div data-scroll data-scroll-call="playVideo">Video section</div>
4. スティッキー要素
<div data-scroll-section>
<div data-scroll data-scroll-sticky>
I stick while section is in view
</div>
</div>
<div id="sticky-container">
<div data-scroll data-scroll-sticky data-scroll-target="#sticky-container">
I stick within #sticky-container
</div>
</div>
5. プログラムによるスクロール
// 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. 横スクロール
const scroll = new LocomotiveScroll({
el: document.querySelector('[data-scroll-container]'),
smooth: true,
direction: 'horizontal'
});
<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. モバイル対応
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
}
});
GSAP ScrollTrigger との連携
Locomotive Scroll と GSAP ScrollTrigger を組み合わせることで、高度なアニメーションを実現できます。
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();
インスタンスメソッド
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);
パフォーマンスの最適化
data-scroll-sectionを使用して、長いページをセクションに分割します。
<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>
-
視差効果を適用する要素を制限します。多すぎるとパフォーマンスに影響する可能性があります。
-
パフォーマンスが低下する場合はモバイルで無効化します。
smartphone: { smooth: false }
- リサイズ時に更新します。
window.addEventListener('resize', () => {
scroll.update();
});
- 不要になったら破棄します。
scroll.destroy();
よくある落とし穴
1. 固定配置の問題
問題:スムーズスクロールを使用すると、position: fixed の要素が正しく動作しません。
解決策:代わりに data-scroll-sticky を使用するか、固定要素をコンテナの外に配置します。
<nav style="position: fixed;">Navigation</nav>
<div data-scroll-container>
</div>
2. 画像が遅延読み込みされない
問題:すべての画像が一度に読み込まれます。
解決策:遅延読み込みと連携させます。
<img data-scroll data-src="image.jpg" class="lazy">
scroll.on('call', (func) => {
if (func === 'lazyLoad') {
// Trigger lazy load
}
});
3. スクロール位置が更新されない
問題:動的コンテンツによってスクロール位置が更新されません。
解決策:DOM の変更後に update() を呼び出します。
// After adding content
addDynamicContent();
scroll.update();
4. アクセシビリティに関する懸念
問題:スクリーンリーダーやキーボード操作が正常に動作しません。
解決策:無効化オプションを用意します。
const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
const scroll = new LocomotiveScroll({
smooth: !prefersReducedMotion
});
5. メモリリーク
問題:ルート変更時(SPA)にスクロールインスタンスがクリーンアップされません。
解決策:アンマウント時に必ず破棄します。
// React example
useEffect(() => {
const scroll = new LocomotiveScroll();
return () => scroll.destroy();
}, []);
6. z-index の競合
問題:視差効果を適用した要素が正しく重なりません。
解決策:視差レイヤーに明示的な z-index を設定します。
[data-scroll-speed] {
position: relative;
z-index: var(--layer-depth);
}
関連スキル
- gsap-scrolltrigger:高度なスクロール連動アニメーション(併用してください)
- barba-js:Locomotive Scroll との統合によるページ遷移
- scroll-reveal-libraries:基本的なフェードイン効果向けの、よりシンプルな代替手段
- react-three-fiber:スクロール連動の3Dシーン(Locomotive のイベントと同期)
- motion-framer:React でのスクロールアニメーションの代替手段
リソース
- スクリプト:
generate_config.py- 設定ジェネレーター、integration_helper.py- GSAP 統合コード - リファレンス:
api_reference.md- API の完全なリファレンス、gsap_integration.md- GSAP ScrollTrigger のパターン - アセット:
starter_locomotive/- サンプル付きの完全なスターターテンプレート