mcpField
L
locomotive-scroll

locomotive-scroll

github.com/freshtechbroデザイン・UI1.2k2.6k 回インストール49 週間前に更新
リポジトリ

locomotive-scroll について

locomotive-scrollは、スクロールを軸にしたWebサイトを作る開発者向けのJavaScriptライブラリです。スムーズスクロールに加え、視差、ビューポート検出、固定要素、横スクロールに対応します。

主な機能

  1. 01調整可能なスムーズスクロール
  2. 02要素単位の視差効果
  3. 03ビューポート検出とスクロールイベント
  4. 04固定要素と横スクロール
  5. 05プログラムによるスクロール

活用シーン

  1. 01ランディングページへの視差追加
  2. 02スクロール進捗とアニメーションの同期
  3. 03スクロール型のストーリーサイト制作

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/freshtechbro/claudedesignskills --skill locomotive-scroll

インストール後、Claude Code で/locomotive-scrollを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

assets/starter_locomotive/
index.html
main.js
package.json
README.md
style.css
references/
api_reference.md
gsap_integration.md
scripts/
generate_config.py
integration_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);

パフォーマンスの最適化

  1. 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>
  1. 視差効果を適用する要素を制限します。多すぎるとパフォーマンスに影響する可能性があります。

  2. パフォーマンスが低下する場合はモバイルで無効化します。

smartphone: { smooth: false }
  1. リサイズ時に更新します。
window.addEventListener('resize', () => {
  scroll.update();
});
  1. 不要になったら破棄します。
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/ - サンプル付きの完全なスターターテンプレート

コメント