Communitygithub.com

apple-scroll-animation

Appleスタイルのスクロール駆動アニメーション(スクロールテリング)を、ライブラリを使わずにプレーンなHTML/CSS/JSで構築します。ユーザーがApple.comのような、スクロールに応じて要素が組み上がったり、発光したり、傾いたり、拡大・切り替わるページを求めている場合に使用します。ピン留め(sticky)セクション、スクロール進行によるサーブ、単語ごとの表示、要素のフライイン、ヘッドレステスト方法をカバーします。

apple-scroll-animation とは?

このスキルは、Appleの製品ページで見られるような、スクロール位置に応じてアニメーションが進行する「スクロールテリング」を、ライブラリ不要で実装するための包括的なガイドです。主なコンセプトは「ピン留め」「進行度の計算」「数値から視覚効果を駆動する」の3つで、具体的なエフェクト(組み立て、単語発光、スッテパー、傾き、カード浮上、拡大など)の実装方法と、実際の開発で得られたベストプラクティス(CSSプロパティの使い分け、パフォーマンス、アクセシビリティなど)を詳細に説明しています。また、`prefers-reduced-motion` への対応や、DevTools Protocolを使ったヘッドレスChromeでのテスト手順も含まれています。このスキールは、Claude CodeやCursor、CodexなどのAIエージェントが、ユーザーの要望に応じてAppleスタイルのスクロールアニメーションを生成する際に、正確で保守性の高いコードを提供するためのリファレンスとして機能します。

対応~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/MananShukla007/apple-scroll-animation/tree/HEAD/skills/apple-scroll-animation

お気に入りのAIに質問する

このエージェントスキルを事前に読み込んだ状態で新しいチャットを開きます。

ドキュメント

Appleスタイルのスクロールアニメーション

エフェクトはスクロール位置によって進行し、タイマーでトリガーされるわけではありません。上にスクロールすると逆再生されます。ライブラリは不要です。

3つのアイデア

  1. ピン留め 背の高いラッパー(例:height: 300vh)が、position: sticky; top: 0; height: 100vh; overflow: hidden の子要素を保持します。子要素は画面に留まり、ラッパーがスクロールして通過します。ラッパーの余分な高さがアニメーションの予算です。
  2. 進行度 1つの関数でスクロール位置を0..1の数値に変換します:
    • ピン留めセクション:clamp(-rect.top / (rect.height - innerHeight))
    • ビューポートに入る要素:clamp((innerHeight*a - rect.top) / (innerHeight*(a-b)))
  3. 数値から視覚効果を駆動 各フレームで translate、rotate、scale、opacity(および borderRadius)を設定します。1つの scroll リスナーを requestAnimationFrame でスロットルしてすべてを再計算します。

すぐに貼り付け可能なエンジン:references/scroll-engine.js

効果的なエフェクト(すべてではなく3~5個選ぶこと)

エフェクト方法
組み立てアイテムをビューポートの端にランダムに配置(ランダムな角度、回転、スケール .35、透明度 .2)し、レイアウト位置にイーズアウトします。各アイテムの自然な位置からのオフセットをロード時/リサイズ時に1度計算し、(1 - ease(p)) を掛けます。インデックスで遅延させます。
単語発光各単語をspanでラップします。clamp(p * 1.25 * N - k) として透明度 .18 → 1 に変化させます。
ピン留めスッテパーstep = floor(p * N);少数部分 p*N - step がアクティブなステップ内の進行バーを埋めます。ステップをクリックするとそのステップの位置に scrollTo します。
傾きフラット端末/デバイスのモックアップに対して perspective(1400px) rotateX((1-e)*22deg) translateY((1-e)*60px) scale(.84 + .16*e) を適用します。
カード浮上translate: 0 (1-e)*80px; scale: .9+.1e; opacity: e、列ごとに遅延させます(i % cols)。
拡大ビデオ/画像の scale .78 → 1、borderRadius 44px → 28px。

進行度を適用する前に ease = t => 1 - (1-t)**3 を使用します。

ルール(苦労して学んだこと)

  • 個別のCSSプロパティ translate、rotate、scale を進行度の適用に使い、transform はホバー用に残しておきます。そうしないとホバーとスクロールが同じプロパティを競合します。
  • 同じ要素に .reveal フェードクラスと進行度駆動の変換を併用しないでください。どちらか一方を選びます。
  • セクションの見出しはコンテンツと一緒にピン留めパネル内に配置します。パネルにコンテンツだけが中央に配置されていると、背の高いモニターでは大きな空白領域が表示されます。
  • スクロール距離は控えめに。Nステップのスッテパーでは約 N * 55vh + 100vh、単発のエフェクトでは 240-300vh にします。700vh以上はユーザーが疲れます。
  • ピン留めするものは100vhに収まるものに制限します。短い画面(max-height: 820px)やスマートフォンでは、字幕や追加要素を非表示にし、スッテパーではアクティブなステップのみ表示します。
  • 動きの抑制:prefers-reduced-motion: reduce の場合、すべての位置で進行度 1 を返します(最終状態、動きなし)。要素を非表示のままにしないでください。
  • Stickyは祖先に overflow を必要としません ただし body の overflow-x: hidden は問題ありません。sticky要素とページの間にあるラッパーに overflow: hidden を設定しないでください。
  • リサイズ時に再計算します(組み立てオフセットはレイアウトに依存します)。
  • translate/rotate/scale/opacity/border-radius のみをアニメーション化し、レイアウトプロパティは避けます。
  • ビデオの最初と最後のごく短いセグメントは避けます:<video> の再生をスクラブする場合、短いクリップは空白を表示する可能性があります。

標準的なページ順序

ヒーロー(ピン留め、組み立て)→ プレーンなステートメント(エフェクトなし)→ 証明/フィルム(拡大)→ ピン留めスッテパー → デバイスモックアップ(傾きフラット)→ カードグリッド(浮上)→ CTA。Appleらしい雰囲気のために黒と薄いグレーのセクションを交互に配置し、アクセントカラーを1つ使用します。

テスト

ヘッドレスChromeの --screenshot はスクロールできません。代わりにDevToolsプロトコルを介して実際のChromeを操作します:

  1. chrome --headless=new --remote-debugging-port=9333 --user-data-dir=/tmp/prof about:blank &
  2. Node(v22以降にはグローバルな WebSocket があります)から:http://localhost:9333/json をfetchし、ページの webSocketDebuggerUrl を開き、Emulation.setDeviceMetricsOverride、Page.navigate を送信し、各位置に対して Runtime.evaluate("scrollTo(0,Y)") を実行し、約700ミリ秒待機し、Page.captureScreenshot を実行します。
  3. 各ピン留めセクションの offsetTop と高さからYを選択します(例:0%、60%、100%)。
  4. デスクトップ(1440x900)、大きな画面(2000x1300)、スマートフォン(390x800)で確認し、document.documentElement.scrollWidth === innerWidth(水平方向のオーバーフローがないこと)を確認します。

納品チェックリスト

  • すべてのエフェクトがスクロール進行度で駆動され、逆方向にも動作すること
  • 動きの抑制(reduced-motion)のフォールバック
  • スマートフォンレイアウトの確認、水平スクロールがないこと
  • ピン留めスクロール長が控えめであること、背の高い画面で空白がないこと
  • 各ピン留めセクションの開始/中間/終了でスクリーンショットを取得すること

関連スキル