CSS

CSSスクロール連動アニメーションの作り方|scroll()実働デモ付き

CSS Scroll-driven Animationsを実働デモで解説。animation-timeline: scroll()、view()、animation-range、進捗バー、フォールバックと使い分けが分かります。

この記事の目次
  1. 結論:進捗はscroll()、要素の出入りはview()
  2. 枠内をスクロールして動きを確認する
  3. スクロール量で進捗バーと円を動かす
  4. scroll()で読了進捗バーを作る
  5. view()で要素の出入りに連動させる
  6. JavaScriptのscrollイベントとの違い
  7. アクセシビリティと動きの抑制
  8. 未対応ブラウザへのフォールバック
  9. 動かないときの確認順
  10. よくある質問
  11. スクロールジャックと同じですか?
  12. JavaScriptは完全に不要ですか?
  13. 本番導入前に何を確認しますか?
  14. まとめ
  15. 関連記事
  16. 参照した公式資料

CSS Scroll-driven Animationsは、経過時間ではなくスクロール量をアニメーションの進捗に使う仕組みです。読了進捗バー、要素が画面へ入る途中の変化、スクロールに追従する図解を、毎回scrollイベントで計算せず表現できます。

情報確認日:2026年8月20日

結論:進捗はscroll()、要素の出入りはview()

選び方

  • scroll():スクロール領域全体の進捗へ連動する
  • view():対象要素がスクロールポートへ出入りする進捗へ連動する
  • animation-range:変化を始める・終える区間を絞る
  • 未対応環境では、内容を隠さず静止表示へ縮退させる
スポンサーリンク

枠内をスクロールして動きを確認する

WORKING DEMO

スクロール量で進捗バーと円を動かす

この枠を下へスクロールしてください。上のバーが伸び、中央の円が左右へ移動します。時間が止まっていても、スクロール位置を戻せばアニメーションも戻ります。

最後まで来ると進捗は100%です。キーボードなら枠へフォーカスして矢印キーやPage Downでも試せます。

scroll()で読了進捗バーを作る

.reading-progress {
  position: fixed;
  inset: 0 0 auto;
  height: 4px;
  transform: scaleX(0);
  transform-origin: left;
  background: #2563eb;
  animation: reading-progress linear both;
  animation-timeline: scroll(root block);
}

@keyframes reading-progress {
  to { transform: scaleX(1); }
}

scroll(root block)はルートスクロール領域のblock方向をタイムラインにします。通常のanimation-durationではなくスクロール位置が進捗を決めるため、ユーザーが戻ればバーも戻ります。

view()で要素の出入りに連動させる

.feature-card {
  opacity: 0.35;
  transform: translateY(2rem);
  animation: reveal linear both;
  animation-timeline: view(block);
  animation-range: entry 10% cover 35%;
}

@keyframes reveal {
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

entryは要素が入り始める区間、coverはスクロールポートとの重なりを基準にする区間です。値を派手にする前に、DevToolsで開始と終了が意図どおりか確かめます。

JavaScriptのscrollイベントとの違い

要件 向く方法 理由
進捗バー・単純な変形 CSS scroll() 宣言的で位置計算が不要
要素が見えたら一度だけ表示 Intersection Observer 状態変更が目的だから
複数場面を固定・同期する演出 GSAP等を検討 複雑なタイムライン制御が必要
分析イベントを送る JavaScript 副作用はCSSでは扱えない

見た目の進捗はCSS、データ送信やアプリ状態の変更はJavaScript、と役割を分けると保守しやすくなります。

アクセシビリティと動きの抑制

スクロールのたびに大きく回転・拡大すると、内容を読む操作そのものが負担になります。装飾に留め、文字の可読性や操作対象の位置を不安定にしないでください。動きを減らす設定には静止表示を用意します。

@media (prefers-reduced-motion: reduce) {
  .feature-card {
    animation: none;
    opacity: 1;
    transform: none;
  }
}

未対応ブラウザへのフォールバック

最初から要素をopacity: 0にして対応環境だけ表示させると、未対応環境で内容が消えます。基本状態は読める見た目にし、@supports内でのみ装飾を追加します。

.feature-card {
  opacity: 1;
}

@supports (animation-timeline: scroll()) {
  .feature-card {
    animation: reveal linear both;
    animation-timeline: view();
  }
}

動かないときの確認順

  1. 対象ブラウザがanimation-timelineへ対応しているか
  2. 実際にスクロールする要素と指定したscrollerが一致するか
  3. animation短縮記法が後からtimelineを初期化していないか
  4. スクロール量がなく、開始と終了が同じになっていないか
  5. prefers-reduced-motionで無効化されていないか

animationを後から指定すると関連プロパティが初期化される場合があります。短縮記法を先、animation-timelineを後に書くと意図が明確です。

よくある質問

スクロールジャックと同じですか?

違います。Scroll-driven Animationsはスクロール位置を進捗に使いますが、ユーザーのスクロール操作を奪う必要はありません。自然なスクロールを保って使います。

JavaScriptは完全に不要ですか?

見た目だけなら不要な場面が増えます。分析、データ取得、状態更新、複雑な制御はJavaScriptが必要です。

本番導入前に何を確認しますか?

対象ブラウザ、動きを減らす設定、キーボードスクロール、長いページ、モバイルの実機、未対応時の静止表示を確認します。

まとめ

スクロール領域全体の進捗にはscroll()、要素の出入りにはview()を使います。CSSで完結する見た目へ絞り、内容を隠さないフォールバックとprefers-reduced-motionを用意すると、安全に導入できます。

関連記事

参照した公式資料

スポンサーリンク