CSS / animation

scroll-driven animations を CSS で対応する

─ Guide to page sections ─

スクロールをトリガーにしたアニメーションを scroll-driven animations を使って構築する。このページでは CSS だけを使って実現する。

プロンプター完成版
スクロールするとフェードアウト・インしたりするサンプル

First

Scroll Progress Timeline

Scroll Progress Timeline は新しいCSSのプロパティだ。ページのスクロール進捗に合わせて連動するアニメーションの実装ができる。表示画面を対象にして、スクロールの開始位置を0%、最下部を100%として、上から下へスクロールの進捗をカウントする。まずは Scroll Progress Timeline のサンプルを見てみよう

View Progress Timeline
Scroll Progress Timeline を使ったアニメーション

これまでのアニメーションについての整理

さて、最初に CSS アニメーションについての整理が必要だと思うので以下にまとめる。

  • これまで親しんできた CSS アニメーションとは、CSSだけでアニメーションすることができる機能のことである。
  • CSS アニメーションは、animation と transition の2種類の方法がある。
  • animation は、@keyframes を使って設定する。
  • animation は、ループが可能である。(transition は不可能)
  • animation は、自動再生が可能である。(transition は hover や checkbox などのトリガーが必要)
  • animation は、再生後にプロパティの継続が可能である。(transition は再生後にプロパティが元に戻る)
    • animation-fill-mode: 再生の開始が遅延されている間の表示、及び再生終了後の表示を設定する。
    • animation-iteration-count: アニメーションを実行する回数を指定する。
    • animation-duration: 再生時間を指定する。
  • animation プロパティで複数のアニメーションを指定する場合はカンマ区切りで記述できる
    animation-name: Jump, MoveRight, FadeInOut;
    animation-duration: 3.5s, 4s, 1s;
    animation-iteration-count: 2, 1, 5;
  • transition プロパティで複数のアニメーションを指定する場合はカンマ区切りで記述できる
    transition: background-color .3s, transform .6s, color 500ms;
  • Web Animations API(WAAPI)は、JavaScript のみでアニメーションを実装できる仕様だ。CSS アニメーションとは異なり、さまざまな関数やイベントと組み合わせて、より柔軟で豊かな表現が可能となる。WAAPI では、CSS アニメーションと同様のことを JavaScript で記述することができる。


Second

一括指定の animation プロパティ

animationプロパティは CSS の一括指定プロパティであり、以下の 8 つのCSS プロパティを一括で指定することができる。各プロパティの値を半角スペースで区切って指定する。(※値は初期値)

一括指定する際の各値の順番は無いが、例外的なのが秒数を指定するプロパティがふたつある。animation-duration が先に、animation-delay を後に記述する。

8 つの CSSプロパティの内、記述していないものは初期値が参照される。

  1. animation-name: none
    …要素に適用される 1 つまたは複数のアニメーションを記述する @keyframes アットルールの名前を指定
  2. animation-duration: 0s
    …1 回のアニメーション周期が完了するまでの所要時間を設定する
  3. animation-timing-function: ease
    …アニメーションの再生速度の変化パターンを設定する
    • ease(初期値)…ゆっくりと始まり、ゆっくりと終わる
    • ease-in…ゆっくりと始まり、一定速度で終わる
    • ease-out…一定速度で始まり、ゆっくりと終わる
    • ease-in-out…ゆっくりと始まり、ゆっくりと終わる
    • linear…最初から最後まで一定の速度で変化する
  4. animation-delay: 0s
    …アニメーションをいつ開始するかを指定する
  5. animation-iteration-count: 1
    …アニメーションを実行する回数を指定する
  6. animation-direction: normal
    …keyframes で作成したアニメーションの向きを指定する。アニメーションの再生方向は、
    • normal
    • reverse…アニメーションを逆方向に実行し、タイミング関数も逆になる。例えば、タイミング関数の ease-in が ease-out になる
    • alternate…アニメーションを毎回反転させ、初回は順方向になる
    • alternate-reverse…アニメーションを毎回反転させ、初回は逆方向)いずれかに設定できる
  7. animation-fill-mode: none
    …CSS アニメーションの実行の前後にどう対象にスタイルを適用するかを設定する
  8. animation-play-state: running
    …アニメーションが実行中か停止中かを設定する(アニメーションの再生を一時停止させる時に使用、たとえば、対象要素にホバーした際にアニメーションを一時停止したい場合に使用する)

Third

View Progress Timeline

View Progress Timeline は新しいCSSのプロパティだ。ページの特定する要素に差し掛かると、その特定する範囲でのスクロール進捗に合わせて連動するアニメーションの実装ができる。特定する要素を対象にして、スクロールの開始位置を0%、最下部を100%として、上から下へスクロールの進捗をカウントする。まずは View Progress Timeline のサンプルを見てみよう

View Progress Timelineの基本的な使い方は、アニメーションさせたい要素の animation-timeline に view() 関数を使い、animation-range でアニメーションが作動する対象の範囲を決め、animation に @keyframes を指定する。

View Progress Timeline
View Progress Timelineの基本的な使い方の例
<main>
  <div class="interval"></p></div>
  <div class="object"></div>
  <div class="interval-2"></div>
  <div class="interval-3"></div>
</main>
main {
  width: 40ch;
  width: 100%;
  margin: auto;
  padding: 0;
  background-color: #f7f7f7;
  box-shadow: 0px 3px 6px 0px #9E9E9E;
}

@keyframes expand-collapse {
  0% {width:0%;}
  25% {width:100%;}
  75% {width:100%;}
  100% {width:0%;}
}

.object {
  height: .5rem;
  width: 0%;
  background-color: #fe001a;
  view-timeline-axis: y; /* 以下にて 説明 ※ 1 */
  animation: auto linear both; /* 以下にて 説明 ※ 2 */
  animation-name: expand-collapse;
  view-timeline-name: --expand-object; /* 説明 ※ 3 */
  animation-timeline: --expand-object; /* 説明 ※ 4 */
  animation-duration: 1ms;
}

※ 1 CSS の 「view-timeline-axis: y」 は、y 軸方向のスクロールを基準にするという意味だ。

※ 2「animation: auto linear both;」の意味は、「auto:」でアニメーションが自動的に実行され、「linear:」で一定の速度で始まって終わり、「both:」でアニメーション再生前の要素のスタイルは最初のキーフレームの状態になる。

※ 3 「view-timeline-name」 は、view progress timeline に名前を付けるものだ。view-timeline-name に許可される値は「none」と「<dashed-ident>」(値は -- で始まる必要がある。

これは、標準の CSS キーワードとの名前の衝突を避けるのに役立つ。)、次の animation-timeline でその名前を使用することができる。

※ 4 「animation-timeline は、アニメーションを識別する名前だ。識別子は、大文字小文字の区別がない英文字 a から z、数字 0 から 9、アンダースコア ( _ )、ダッシュ ( - ) から成る。最初のダッシュ以外の文字は英文字でなければならない。


Fourth

animation-range

Scroll Progress Timeline と View Progress Timeline は、animation-range と組み合わせることで、スクロール連動型アニメーションの進行度を詳細に指定することができる。以下はその値についての説明である。

  • animation-range: cover
    …スクロールポート(Scrollport)の全範囲がアニメーションの対象になる。
  • animation-range: entry
    …スクロールポートに要素が入って出るまでの範囲がアニメーションの対象になる。
  • animation-range: exit
    …スクロールポートに要素が出て見えなくなるまでの範囲がアニメーションの対象になる。
  • animation-range: entry-crossing
    …スクロールポートの終了境界線を横切っている範囲がアニメーションの対象になる。
  • animation-range: exit-crossing
    …スクロールポートの開始境界線を横切っている範囲がアニメーションの対象になる。
  • animation-range: contain
    …要素がスクロールポートに入っている範囲がアニメーションの対象になる。

animation-range のサンプルで各種の挙動を確認する

言葉では解り辛いのでanimation-range の値別挙動を見てみよう

animation-range の値別表示
animation-range の各種値別の挙動を確認する

animation-range の挙動を確認する

animation-range プロパティの各値での挙動は、scroll-driven-animations ジェネレーター でも確かめることができる。

animation-range の挙動の比較を確認する

animation-timeline: view(); を使ったページに animation-range: の値を変更して比較してみる。以下では画像表示のはじまりのタイミングが異なる設定を確認する。

animation-range の挙動の比較を確認する
entry 50% と entry 25% の違いを確認する

Fifth

scroll-driven animations 総括

未対応のブラウザ対策

対応ブラウザは Chrome と Edge に対応しているが Firefox には未対応なので、以下の対応が必要である。日本語では「このブラウザでは、スクロール駆動のアニメーションはサポートされていません。 Chrome もしくは Edge で試してください。」という具合に、「Warning」を表示する。

非対応のブラウザ対策
非対応(Firefox など)のブラウザに Warning を表示する

html は <body> 直下に、css を以下のように記述する。

<div class="warning">
  <p> Scroll-driven animations are not supported in this browser. Try this page in Chrome 115+.</p>
</div>
/* Warning for unsupported browsers */
.warning {
  color: black;
  background: papayawhip;
  margin-inline: -1rem;
  padding: 1rem;
}

@supports (animation-timeline: scroll()) {
  .warning {
   display: none;
  }
}
/* //Warning for unsupported browsers */

実装する方法

スクロールと連動するスクラブアニメーション(スクロール量や位置に応じてアニメーションを変化させる動き)の実装を行うには、以下ふたつの方法がある。

Scroll Progress Timeline

①@keyframesルールでアニメーションを用意し、アニメーションさせる要素に指定する。
②animation-timelineプロパティに scroll() 関数を指定する。
③animation-rangeプロパティを設定する。

View Progress Timeline

①@keyframesルールでアニメーションを用意し、アニメーションさせる要素に指定する。
②animation-timelineプロパティに view() 関数を指定する。
③animation-rangeプロパティを設定する。

締めくくりとして、冒頭に掲げた「scroll-driven animations」の実用的なトリックの完成形を提示する。

画像を jpg と avif を <picture> 要素を使って併記する

avif は画像を超圧縮できる次世代型画像ファイル形式である。avif を対応のブラウザも非対応のブラウザも解決するための手法が picture 要素である。picture 要素は HTML5 から新たに追加された要素であり、ユーザーの閲覧環境に応じて最適な画像を表示させることができる。

Squoosh(スクーシュ)は、Googleが開発した画像圧縮ツール、webp や jpeg、png などの画像形式に変換したり、リサイズすることができる。Squooshは、2018年に公開。