🔥

【CSS】スクロールと連動するアニメーションをJavaScriptを使わずに実装してみる

に公開

はじめに

アニメーションをスクロールと連動させる際には、基本的にJavaScriptが必要になります。しかし、Scroll-driven Animationsを使用することによって、なんとCSSだけで実装できるようになります。「リッチなアニメーションを実装したいんだけど、JavaScriptには苦手意識があって...」というような方にとっては救世主になるのではないでしょうか。
この記事では、Scroll-driven Animationsの基本的な使い方やサンプルについて解説します。

そもそもScrol-driven Animationsって?

https://developer.chrome.com/blog/new-in-chrome-115?hl=ja
Scroll-driven AnimationsはChrome115で実装された新機能です。シンプルなCSSだけで、スクロール量と連動したアニメーション(スクラブアニメーション)を実装できるようになりました。実装の手軽さだけでなく、JavaScriptを使わないことによるページパフォーマンスの向上も期待できます。

このアニメーションのタイムラインには2つの種類があります。

  • Scroll Progress Timeline
  • View Progress Timeline

これらを使い分けることで、異なった挙動のアニメーションが実装できます。

Scroll Progress Timeline

スクロールできるコンテナ全体を基準にしたもの。スクロールの開始位置を0%・終了位置を100%として、アニメーションの進捗を管理します。

サンプル

ブログ系のサイトでたまに見かける読了率メーターを実装します。
Scroll Progress Timeline
任意の要素に対し、水平方向のscale0から1へアニメーションさせます。
アニメーションの内容自体はkeyframesで定義しておきます。animation-timelineプロパティにscroll()を指定することで、定義したアニメーションをスクロールと連動させることができます。

index.html
<body>
  <div class="progress">
    <div class="progress-bg"></div> <!-- 進捗バーの背景 -->
    <div class="progress-bar"></div> <!-- 進捗バー本体 -->
  </div>
</body>
style.css
/* Scroll Progress Timeline */
/* 進捗バー本体(これのサイズを変動させます) */
.progress-bar {
  position: fixed;
  top: 0;
  left: 0;
  width: 100vw;
  height: 12px;
  background-color: darkorange;
  transform-origin: left center;
  animation: readingProgress linear;
  animation-timeline: scroll(); /* アニメーションタイムライン scroll()を指定 */
}
/* 進捗バーの背景(なくても構いません) */
.progress-bg {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 12px;
  background-color:  #ccc;
}
/* 水平方向にサイズを変動 */
@keyframes readingProgress {
  from {
    scale: 0 1;
  }
  to {
    scale: 1 1;
  }
}

※ bodyの高さを指定するなどして、ある程度スクロールできるよう調整してください。

View Progress Timeline

ビューポートを基準にしたもの。ビューポートの最下端を0%、反対側の端に到達すると100%としてアニメーションの進捗を管理します。

サンプル

画面内に要素が入ってきた時に、スクロールと連動して要素を回転させる仕組みを実装します。
View Progress Timeline
任意の要素のrotate()0から180degにアニメーションさせます。Scroll Progressと同様に、アニメーションの内容自体はkeyframesで定義し、あとはanimation-timelineにview()を指定すればOKです。
また、今回はanimation-rangeというプロパティによりアニメーションの開始位置と終了位置の微調整を行うことが可能です。MDNの解説を見ていただければ分かるとおり、値が多数あり複雑です。View Timeline Ranges Visualizerというツールを使うと、イメージも湧きやすく実装の助けになるかと思われます。

index.html
<body>
  <div class="rotate"></div>
</body>
style.css
/* View Progress Timeline */
.rotate {
  position: relative;
  width: 240px;
  aspect-ratio: 1/1;
  margin: 4em auto;
  background-color: darkorange;
  animation: circle linear both;
  animation-timeline: view(); /* アニメーションタイムライン view()を指定 */
  animation-range: cover 0% cover 50%; /* 開始: 要素がビューポートに完全に入った時、終了: ビューポートの真ん中 */
}
/* 回転 */
@keyframes rotate {
  from {
    transform: rotate(0);
  }
  to {
    transform: rotate(180deg);
  }
}

※ bodyの高さを指定するなどして、ある程度スクロールできるよう調整してください。

対応ブラウザ

2024年6月17日現在、ブラウザの対応状況は以下のようになっています。
caniuse:animation-timeline

Safari・Firefoxではまだ対応が進んでいないようですね。

まとめ

CSSだけを使ってスクラブアニメーションを実装する方法について解説しました。先述したように、まだ全てのモダンブラウザが対応しているわけではありませんが、時間の問題ではないでしょうか。今のうちに様々な演出を試してみてはいかがでしょう。

参考サイト

今回の記事を作成するにあたり参考にさせていただきました。ありがとうございます!

Discussion