Scroll-driven AnimationsでCSSでの実装が大きく変わる! スクロールをトリガーにしたアニメーションを実装する方法
Post on:2023年7月13日
まもなくリリースされるChrome 115で実装されるScroll-driven Animationsにより、スクロールをトリガーにしたアニメーションの実装方法が大きく変わります。
スクロールすると要素がアニメーションで表示されたり、スクロール量で変化するインジケーター、背景が変化するパララックスなど、実装がそれなりに手間がかかりましたが、数行のコードで実装できるようになります。スクロールをトリガーにしたアニメーションを実装するこれからの方法を紹介します。
Animate elements on scroll with Scroll-driven animations
by Bramus
下記は各ポイントを意訳したものです。
※元サイト様のライセンスに基づいて翻訳しています。基づいてというのは、貢献部分が同ライセンスも含みます。
- はじめに
- Webのアニメーション、ちょっとだけおさらい
- アニメーションのタイムライン
- スクロール進行状況タイムラインの使い方
- ビュー進行状況タイムラインの使い方
- さらに試してみたいこと
- その他のデモとリソース
はじめに
スクロール駆動のアニメーションは、Webでよく使用されるUXパターンです。スクロール駆動のアニメーションとは、スクロールコンテナのスクロール位置と連動してアニメーションするものです。上下にスクロールすると、連動したアニメーションが直接反応して前後にスクラブします。
たとえば、パララックス背景画像や下記のようなスクロールに応じて変化するインジケーターなどのエフェクトがあります。
また、スクロール駆動のアニメーションには、コンテナ内の要素の位置と連動したアニメーションもあります。たとえば、ビューポート内に要素が表示されたときにフェードインさせるエフェクトです。
このようなエフェクトを実装するための古典的な方法は、メインスレッドでスクロールイベントに応答することですが、これは次の2つの問題が発生します。
- モダンブラウザはスクロールを別プロセスで実行するため、スクロールイベントは非同期で配信されます。
- メインスレッドのアニメーションはジャンクの影響を受けます。
そのため、スクロールと同期したパフォーマンス性の高いスクロール駆動のアニメーションを実装することは不可能か、非常に困難です。
Chromeに導入されるのは既存のWeb Animations API(WAAPI)とCSS Animations APIと連携して動作し、宣言型のスクロール駆動アニメーションを可能にする新しいAPIとコンセプトのセットです。
スクロール駆動のアニメーションを既存の2つのAPIと統合することは、これらのAPIの利点を活用できることを意味します。その中にはメインスレッドからアニメーションを実行させる機能も含まれています。数行のコードを記述するだけで、メインスレッドからスクロール駆動のシルクのように滑らかなアニメーションを実行できるようになりました。
これほど素晴らしいことはないですね!
この記事を読み切れない場合は、Scroll-driven Animationsにアクセスしてください。スクロール駆動のアニメーションのデモやツールが満載です。
Webのアニメーション、ちょっとだけおさらい
CSSで実装するWebのアニメーション
CSSでアニメーションを実装するには、@keyframes
を使用してキーフレームを定義します。それをanimation-name
プロパティで要素にリンクし、animation-duration
を設定して、アニメーションの時間を設定します。animation-easing-function
やanimation-fill-mode
など、ほかにもanimation-*
の省略形プロパティがありますが、これらはすべてanimation
のショートハンドで使用できます。
たとえば、ある要素をX軸方向に拡大し、背景色を変化させるアニメーションがあります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
@keyframes scale-up { from { background-color: red; transform: scaleX(0); } to { background-color: darkred; transform: scaleX(1); } } #progressbar { animation: 2.5s linear forwards scale-up; } |
JavaScriptで実装するWebのアニメーション
JavaScriptではWeb Animation APIを使用して、まったく同じことを実現できます。Animation
とKeyFrameEffect
のインスタンスを新規に作成するか、より短いElement animate()
メソッドを使用します。
1 2 3 4 5 6 7 8 9 10 11 |
document.querySelector('#progressbar').animate( { backgroundColor: ['red', 'darkred'], transform: ['scaleX(0)', 'scaleX(1)'], }, { duration: 2500, fill: 'forwards', easing: 'linear', } ); |
このJavaScriptの視覚的な結果は、前述のCSSバージョンと同じです。
アニメーションのタイムライン
デフォルトでは、ある要素につけられたアニメーションはドキュメントのタイムライン上で実行されます。ページが読み込まれたときに0から始まり、時間の経過に伴った変化します。これがデフォルトのアニメーションのタイムラインで、これまではアクセスできる唯一のアニメーションのタイムラインでした。
スクロール駆動のアニメーションの仕様では、新しいタイプのタイムラインが2つ定義されています。
-
- Scroll Progress Timeline
- スクロール進行状況タイムライン、特定の軸に沿ったスクロールコンテナのスクロール位置に連動するタイムラインです。
-
- View Progress Timeline
- ビュー進行状況タイムライン、スクロールコンテナ内の特定の要素の相対位置に連動するタイムラインです。
スクロール進行状況タイムライン
スクロール進行状況タイムライン(Scroll Progress Timeline)は、スクロールコンテナ(スクロールポートやスクローラーと呼ばれるもの)のスクロール位置の進行状況に連動するアニメーションタイムラインで、スクロール範囲内の位置を進行状況のパーセントに変換します。
スクロールの開始位置は0%の進捗状況を表し、終了位置は100%を表します。下記のデモは、スクローラーを上から下にスクロールすると、進捗が0%から100%にカウントされます。
スクロール進行状況タイムラインの視覚化。コンテナ内をスクロールしてみてください。
ビュー進行状況タイムライン
ビュー進行状況タイムライン(View Progress Timeline)は、スクロールコンテナ内の特定の要素の相対的な進捗に連動します。スクロール進行状況タイムラインと同様に、スクローラーのスクロールオフセットが追跡されます。異なるのは、進行状況を決定するのがスクローラー内の主題の相対位置です。
これはIntersectionObserver
の仕組みと似ており、ある要素がスクローラー内でどれだけ表示されているかを追跡することができます。もしその要素がスクローラーに表示されなければ、要素は交差していません。どんなに小さくな部分だけであってもスクローラー内に表示されている場合、それは交差しています。
ビュー進行状況タイムラインは、ある要素がスクローラーと交差し始めた瞬間から始まり、ある要素がスクローラーと交差しなくなった時点で終わります。下記のデモは、ある要素がスクロールコンテナに入った時点で0%からカウントを始め、離れた時点で100%に達していることが確認できます。
ビュー進行状況タイムラインの視覚化。コンテナ内をスクロールしてみてください。
スクロール進行状況タイムラインの使い方
CSSで匿名のスクロール進行状況タイムラインを作成する
CSSでスクロールタイムラインを作成するもっとも簡単な方法は、scroll()
関数を使用することです。これにより、匿名のスクロールタイムラインが作成され、新しいanimation-timeline
プロパティの値として設定できます。
1 2 3 4 5 6 |
@keyframes animate-it { … } .subject { animation: animate-it linear; animation-timeline: scroll(root block); } |
scroll()
関数は、<scroller>
および<axis>
引数を受け入れます。
<scroller>
の値は次のとおりです。
nearest
: もっとも近い祖先のスクロールコンテナを使用します(デフォルト)。root
: ドキュメントビューポートをスクロールコンテナとして使用します。self
: 要素自体をスクロールコンテナとして使用します。
<axis>
の値は次のとおりです。
block
: スクロールコンテナのブロック軸に沿った進行状況の指標を使用します(デフォルト)。inline
: スクロールコンテナのインライン軸に沿った進行状況の指標を使用します。y
: スクロールコンテナのy軸に沿った進行状況の指標を使用します。x
: スクロールコンテナのx軸に沿った進行状況の指標を使用します。
たとえば、ブロック軸のルートスクローラーにアニメーションをバインドする場合、scroll()
に渡す値はroot
とblock
です。まとめると、値はscroll(root block)
になります。
重要
スクロール進行状況タイムラインを使用する場合、animation-duration
を秒単位で設定しても意味がないため、animation-duration
をauto
に設定する必要があります。また、上記のコードのようにanimation-duration
を省略するとデフォルト値であるauto
が設定されます。
下記のデモでは、ビューポートの上部に読み取り進行状況インジケーターが表示されています。ページをスクロールすると、プログレスバーが表示され、ドキュメントの最後に到達するとビューポートの幅いっぱいに表示されます。アニメーションを駆動するためには、匿名のスクロール進行状況タイムラインが使用されています。
この読み取り進行状況インジケーターは、position: fixed;
で上部に固定されています。アニメーションを活性するためには、width
をアニメーションするのではなく、transform
でX軸に対して拡大縮小します。
1 2 3 4 |
<body> <div id="progress"></div> … </body> |
CSSは、下記の通りです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
@keyframes grow-progress { from { transform: scaleX(0); } to { transform: scaleX(1); } } #progress { position: fixed; left: 0; top: 0; width: 100%; height: 1em; background: red; transform-origin: 0 50%; animation: grow-progress auto linear; animation-timeline: scroll(); } |
#progress
要素のアニメーションgrow-progress
のタイムラインは、scroll()
で作成された匿名タイムラインに設定されます。scroll()
には引数を与えないので、デフォルト値が使用されます。
追跡するデフォルトのスクローラーはnearest
で、デフォルトの軸はblock
です。これは、#progress
要素のブロック方向を追跡しながら、最も近いスクローラーであるルートスクローラーを効果的にターゲットにします。
CSSで名前付きスクロール進行状況タイムラインを作成する
スクロール進行状況タイムラインを設定する別の方法は、名前付きタイムラインを使用することです。冗長になりますが、親スクローラーやルートスクローラーをターゲットにしていない場合、ページが複数のタイムラインを使用しているときや自動ルックアップが機能しないときに便利な方法です。こうすることで、指定した名前によってスクロール進行状況タイムラインを特定できます。
要素に名前付きスクロール進行状況タイムラインを作成するには、スクロールコンテナのscroll-timeline-name
プロパティに任意の識別しを設定します。値は--
で始まる必要があります。
1 |
scroll-timeline-name: --my-scroller; |
どの軸を追跡するかを設定するには、scroll-timeline-axis
プロパティを使用します。指定できる値は、scroll()
の<axis>
引数と同じです。
1 |
scroll-timeline-axis: inline; |
最後にアニメーションをスクロール進行状況タイムラインに連動させるためには、アニメーションが必要な要素のanimation-timeline
プロパティをscroll-timeline-name
に設定した識別子と同じ値に設定します。
1 2 3 4 5 6 7 8 9 10 11 |
@keyframes animate-it { … } .scroller { scroll-timeline-name: --my-scroller; scroll-timeline-axis: inline; } .scroller .subject { animation: animate-it linear; animation-timeline: --my-scroller; } |
必要に応じて、scroll-timeline
のショートハンドでscroll-timeline-name
とscroll-timeline-axis
の両方を設定することもできます。
1 |
scroll-timeline: --my-scroller inline; |
重要
名前付きの場合でも要素からスクローラーへのルックアップは先祖間でのみ行われることに注意してください。兄弟要素など、先祖以外の要素をターゲットにする方法はこの記事の下の方で解説しています。
下記のデモでは、カルーセル内の画像の上に表示されるステップインジケーターを採用しています。カルーセル内に画像が3つある場合、インジケーターは33%の幅で始まり、3つのうち1つを表示していることを示しています。最後の3つ目の画像を表示すると、インジケーターは全幅を占めます。アニメーションの駆動には名前付きスクロール進行状況タイムラインが使用されています。
基本となるHTMLは、下記の通りです。
1 2 3 4 5 6 7 |
<div class="gallery" style="--num-images: 2;"> <div class="gallery__scrollcontainer"> <div class="gallery__progress"></div> <div class="gallery__entry">…</div> <div class="gallery__entry">…</div> </div> </div> |
CSSは、下記の通りです。
.gallery__progress
要素は、ラッパーの.gallery
要素内に絶対位置で配置されています。初期静は--num--images
のカスタムプロパティによって設定されています。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
.gallery { position: relative; } .gallery__progress { position: absolute; top: 0; left: 0; width: 100%; height: 1em; transform: scaleX(calc(1 / var(--num-images))); } |
.gallery__scrollcontainer
は、含まれている.gallery__entry
要素を水平に配置し、スクロールさせる要素です。スクロール位置を追跡することで、.gallery__progress
はアニメーション化されます。これは名前付きスクロール進行状況タイムライン--gallery__scrollcontainer
を参照することでおこなわれています。
1 2 3 4 5 6 7 8 9 10 11 12 |
@keyframes grow-progress { to { transform: scaleX(1); } } .gallery__scrollcontainer { overflow-x: scroll; scroll-timeline: --gallery__scrollcontainer inline; } .gallery__progress { animation: auto grow-progress linear forwards; animation-timeline: --gallery__scrollcontainer; } |
注意
このデモでは、匿名のスクロール進行状況タイムラインでは機能しません。gallery__progress
にanimation-timeline: scroll(nearest inline);
を設定すると、たとえばその要素が直接の親であっても.gallery__scrollcontainer
からスクロールを見つけることはできません。
その理由は、nearest
のルックアップは、その位置とサイズに影響を与えることができる要素のみを考慮するからです。.gallery__progress
は絶対位置のため、そのサイズと位置を決定する最初の親要素は.gallery
要素でpotision: relative;
が設定されており、それによってgallery__scrollcontainer
要素を飛び越えています。
専門的な言葉でいうと、ルックアップはもっとも近いスクロールコンテナを見つけるために、含まれているブロックチェーンをたどります。
JavaScriptでスクロール進行状況タイムラインを作成する
avaScriptでスクロールのタイムラインを作成するには、ScrollTimeline
クラスの新しいインスタンスを作成します。追跡したいsource
と軸axis
をプロパティバッグに渡します。
source
: 追跡したいスクローラーを持つ要素への参照。ルートスクローラーを対象にする場合はdocument.documentElement
を使用します。axis
: 追跡したい軸を設定します。値はblock
,inline
,x
,y
です。
1 2 3 |
const tl = new ScrollTimeline({ source: document.documentElement, }); |
これをWebのアニメーションにするには、timeline
プロパティとして渡します。duration
がある場合は省略します。
1 2 3 4 5 |
$el.animate({ opacity: [0, 1], }, { timeline: tl, }); |
JavaScriptを使用したバージョンは、デモページをご覧ください。
HTMLは同じですが、JavaScriptでインジケーターを実装するには、次のJavaScriptを使用します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
const $progressbar = document.querySelector('#progress'); $progressbar.style.transformOrigin = '0% 50%'; $progressbar.animate( { transform: ['scaleX(0)', 'scaleX(1)'], }, { fill: 'forwards', timeline: new ScrollTimeline({ source: document.documentElement, }), } ); |
見た目はCSSバージョンとまったく同じですが、JavaScriptバージョンは作成されたタイムラインはルートスクローラーを追跡し、ページをスクロールするにつれてx軸の#pregress
を0%から100%に拡大表示しています。
ビュー進行状況タイムラインの使い方
CSSで匿名のビュー進行状況タイムラインを作成する
CSSでビュー進行状況タイムラインを作成する方法は、view()
関数を使用します。引数は<axia>
と<view-timeline-inset>
です。
<axia>
: スクロール進行状況タイムラインと同じで、追跡したい軸を設定します。デフォルトはblock
です。<view-timeline-inset>
: 要素がビューポート内にあるかどうかを考慮するときに、オフセット(正または負)を設定できます。値はパーセントまたはauto
で、デフォルトはauto
です。
たとえば、ブロック軸上のスクローラーと交差する要素にアニメーションをバインドするにはview(block)
を使用します。scroll()
と同様に、animation-timeline
プロパティの値として設定し、animation-duration
をauto
に設定することを忘れないでください。
次のコードを使用すると、スクロール中にビューポートを横切ったときにすべてのimg
がフェードインします。
1 2 3 4 5 6 7 8 9 |
@keyframes reveal { from { opacity: 0; } to { opacity: 1; } } img { animation: reveal linear; animation-timeline: view(); } |
重要
ビュータイムラインの<scroller>
は常にもっとも近い親スクローラーの要素を追跡するため、決定することはできません。
息ぬき: タイムラインの範囲を表示
デフォルトでは、ビュータイムラインにリンクされたアニメーションは、タイムラインの全範囲に添付されます。これは、要素がスクロールポートに入ろうとする瞬間から始まり、要素がスクロールポートから完全に離れたときに終了します。
また、ビュータイムラインの特定の部分にリンクさせることも可能で、その場合は範囲を指定します。たとえば、要素がスクローラーに入った時だけ、といった感じです。下記のデモでは、要素がスクロールコンテナに入ったときに0%からカウントを開始しますが、完全に交差した瞬間からすでに100%に達しています。
ターゲットにできるビュータイムラインの範囲は次のとおりです。
cover
: ビュー進行状況タイムラインの全範囲を表します。entry
: 主要ボックスがビュー進行状況の可視範囲に入る範囲を表します。exit
: 主要ボックスがビュー進行状況の可視範囲を出るまでの範囲を表します。entry-crossing
: 主要ボックスが終了ボーダーエッジを横切る範囲を表します。exit-crossing
: 主要ボックスが開始ボーダーエッジを横切る範囲を表します。contain
: 主要ボックスがスクロールポート内のビュー進行状況の可視範囲に完全に含まれるか、完全にカバーされる範囲を表します。これは、被写体がスクローラーよりも高いか低いかに依存します。
範囲を定義するには、範囲開始と範囲終了を設定する必要があります。それぞれは範囲名(上記のリスト)とその範囲名内の位置を決定する範囲オフセットで構成されています。範囲のオフセットは通常、0%
から100%まで
のパーセント表記ですが、20em
のような固定長を設定することも可能です。
たとえば、要素が入った瞬間からアニメーションを実行したい場合は、範囲開始としてentry 0%
を設定します。要素が入るまでに終了させたい場合は、範囲終了としてentry 100%
を設定します。CSSでは、animation-range
でこれを設定します。
1 |
animation-range: entry 0% entry 100%; |
下記のデモでは、それぞれの範囲名が何を表しているのか、パーセントが開始位置と終了位置にどのように影響するのかを確認できます。範囲開始をentry 0%
にし、範囲終了をcover 50%
に設定し、スクロールバーをドラッグしてアニメーションの結果を確認してみてください。
このタイムライン範囲表示ツールを使用して気がついたことがあります。範囲名と範囲オフセットの組み合わせてで、2種類の範囲を対象にできるものがあります。たとえば、entry 0%
, entry-crossing 0%
, cover 0%
はすべて同じ範囲を対象としています。
範囲開始と範囲終了が同じ範囲名をターゲットにしており、0%から100%までの全範囲を対象とする場合、値を短縮して単に範囲名とすることができます。たとえば、animation-range: entry 0% entry 100%;
は、より短いanimation-range: entry;
に書き換えることができます。
重要
これらの範囲は、要素の未変換の主ボックスから導き出されることに注意してください。つまり、範囲を導き出す際にスケールやトランスレートなどの変換は考慮されません。これは良いことで、スクロール中に利用可能なスクロール領域に影響を与えることなく、要素を拡大縮小できます。変換されたボックスを使用した場合は、スクロール領域の変化に応じて常に再計算する必要があるため、アニメーションがちらつく可能性があります。
下記のデモでは、スクロールポートに入ると画像がフェードインします。これは匿名ビュータイムラインを使用しています。アニメーションの範囲が調整され、各画像がスクロールポートの半分に入ったときに完全な不透明になるようにしました。
この拡張したエフェクトは、アニメーション化されたクリップパスで実現されています。CSSは、下記の通りです。
1 2 3 4 5 6 7 8 9 10 |
@keyframes reveal { from { opacity: 0; clip-path: inset(0% 60% 0% 50%); } to { opacity: 1; clip-path: inset(0% 0% 0% 0%); } } .revealing-image { animation: auto linear reveal both; animation-timeline: view(); animation-range: entry 25% cover 50%; } |
CSSで名前付きビュー進行状況タイムラインを作成する
スクロール進行状況タイムラインに名前付きがあるのと同様に、ビュー進行状況タイムラインにも名前付きのバージョンを作成できます。scroll-timeline-*
の代わりに、view-timeline-
を使用して、view-timeline-name
とview-timeline-axis
を使用します。
同じタイプの値が適用され、名前付きタイムラインを検索するための同じルールが適用されます。
前述の画像公開のデモを再加工し、修正されたコードは下記の通りです。
1 2 3 4 5 6 7 8 |
.revealing-image { view-timeline-name: --revealing-image; view-timeline-axis: block; animation: auto linear reveal both; animation-timeline: --revealing-image; animation-range: entry 25% cover 50%; } |
view-timeline-name: revealing-image
を使用すると、要素はもっとも近いスクローラー内で追跡されます。そして、同じ値がanimation-timeline
プロパティの値として使用されます。視覚的な出力は、前述とまったく同じです。
JavaScriptでビュー進行状況タイムラインを作成する
JavaScriptでビュー進行状況タイムラインを作成するには、ViewTimeline
クラスの新しいインスタンスを作成します。追跡するsubject
, axis
, inset
をプロパティバッグに渡します。
subject
: 独自のスクローラー内で追跡する要素への参照。axis
: 追跡する軸。CSSのバリアントと同様にblock
,inline
,x
,y
が使用可能な値です。inset
: ボックスが表示されているかどうかを決定するときのスクロールポートのインセット(正)またはアウトセット(負)の調整。
1 2 3 |
const tl = new ViewTimeline({ subject: document.getElementById('subject'), }); |
これをアニメーションにするにはtimeline
プロパティとして渡し、duration
がある場合は省略します。
1 2 3 4 5 |
$el.animate({ opacity: [0, 1], }, { timeline: tl, }); |
アニメーションさせる要素$el
とsubject
は同じ要素である必要はありません。つまり、DOMツリーのどこかにある遠くの要素をアニメーションさせながら、そのスクローラーで要素を追跡できることを意味します。
さらに試してみたいこと
1つのキーフレームで複数のビュータイムライン範囲にアタッチする
この連絡先リストのデモでは、アイテムがアニメーションで表示されます。アイテムが下からスクロールポートに入るとスライド+フェードインし、上から出るとスライド+フェードアウトします。
このデモでは、各要素は1つのビュー進行状況タイムラインで実装されており、スクロールポートを通過する要素を追跡し、2つのスクロール駆動アニメーションがそれにアタッチされています。animate-in
のアニメーションはタイムラインのentry
範囲に、animate-out
のアニメーションはexit
範囲にアタッチされます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
@keyframes animate-in { 0% { opacity: 0; transform: translateY(100%); } 100% { opacity: 1; transform: translateY(0); } } @keyframes animate-out { 0% { opacity: 1; transform: translateY(0); } 100% { opacity: 0; transform: translateY(-100%); } } #list-view li { animation: animate-in linear forwards, animate-out linear forwards; animation-timeline: view(); animation-range: entry, exit; } |
2つの異なる範囲にアタッチされた2つの異なるアニメーションを実行する代わりに、範囲情報をすでに含む1セットのキーフレームを作成することもできます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
@keyframes animate-in-and-out { entry 0% { opacity: 0; transform: translateY(100%); } entry 100% { opacity: 1; transform: translateY(0); } exit 0% { opacity: 1; transform: translateY(0); } exit 100% { opacity: 0; transform: translateY(-100%); } } #list-view li { animation: linear animate-in-and-out; animation-timeline: view(); } |
キーフレームには範囲情報が含まれているため、アニメーション範囲を指定する必要はありません。 結果は前述とまったく同じです。
非祖先のスクロールタイムラインにアタッチする
この機能はChrome 116で実験的Webプラットフォーム機能フラグを有効にしてください。
名前付きスクロールタイムラインと名前付きビュータイムラインの検索メカニズムは、スクロールの祖先のみに限定されています。しかし、アニメーションが必要な要素が追跡する必要のあるスクロールの子ではないことがよくあります。
これを実現させるのが、timeline-scope
プロパティです。このプロパティを使用すると、タイムラインを実際に作成することなく、その名前のタイムラインを宣言できます。これにより、その名前を持つタイムラインの範囲が広がります。実際には、親要素を共有する際にtimeline-scope
プロパティで子スクローラーのタイムラインを親要素にアタッチできます。
1 2 3 4 5 6 7 8 9 10 |
.parent { timeline-scope: --tl; } .parent .scroller { scroll-timeline: --tl; } .parent .scroller ~ .subject { animation: animate linear; animation-timeline: --tl; } |
このCSSを説明すると、
.parent
要素は--tl
という名前のタイムラインを宣言しています。その子であればanimation-timeline
プロパティの値として使用できます。.scroller
要素は実際には--tl
という名前のタイムラインを宣言しています。デフォルトでは子要素のみ表示されますが、.parent
がscroll-timeline-root
として認定されているため、子要素にアタッチされます。.subject
要素は--tlという名前のタイムラインを宣言しています。祖先のツリーをたどると、 .parent
の--tl
が.scroller
の--tl
を指しているため、.subject
は実質的には.scroller
のスクロール進行状況タイムラインを追跡します。
つまり、timeline-root
を使用すると、タイムラインを祖先に移動 (別名ホイスティング) させることができ、祖先のすべての子がタイムラインにアクセスできるようになります。
timeline-scope
プロパティは、スクロールタイムラインとビュータイムラインの両方で使用できます。
その他のデモとリソース
この記事で解説したデモはすべて、Scroll-driven Animationsにあります。このサイトではスクロール駆動のアニメーションで何が可能になるのかを伝えるためにさらに多くのデモがあります。
デモだけでなく、ツールもたくさんあります。
スクロール駆動のアニメーションについては、Google I/O ’23のWhat’s new in Web Animationsでも取り上げられています。
sponsors