Chrome はスクロール トリガー アニメーションを搭載しており、これを備えた最初のブラウザです。 Chrome 146 に更新すると、正方形の背景が一定時間フェードインする以下のデモが表示されます。 300msただし、要素全体がビューポート内にあるのは 1 回だけです。
スクロールの仕方とは少し違いますが、ドリブン アニメーションは動作するので、この記事ではアニメーションを比較し、スクロール トリガー アニメーションがどのように動作するかを説明します。
スクロールによってトリガーされるアニメーションは、特定のスクロールしきい値を超えた後、一定期間実行されます。 (CSS アニメーション用の JavaScript の Intersection Observer API を考えてください。)
これは、アニメーションの進行状況がスクロールの進行状況と同期する、スクロール駆動のアニメーションとは異なります (animation-timeline: scroll()) または交差度 (animation-timeline: view()) なのでピリオドはありません。
主要な部分は timeline-trigger: view() の代わりに animation-timeline: view()測定する代わりに要素が範囲内に入るのを待ちます いくら その中で、それに応じて何かをしているのです。ただし、実際のことから始めましょう @keyframes を設定するアニメーション background: :
/* Define the animation */
@keyframes fade-bg-in {
to {
background: currentColor;
}
}
に設定されています .square の時期に 300ms: :
.square {
/* Declare animation */
animation: fade-bg-in 300ms;
}
デフォルトでは、宣言が適用されると CSS アニメーションがトリガーされますが、以下の拡張スニペットでは、 timeline-trigger その動作を上書きします。要素が到着するとアニメーションが開始されます view()。 --trigger 一方、これはトリガーの識別子として機能する単なる破線です。 entry 100% exit 0% タイムラインには制限があります。タイムライン範囲は、アニメーションがアクティブ化され、アクティブな状態を維持できるスクロール ゾーンを指定します。
この場合、アニメーションは下端がオンになったときにトリガーされます。 .square (を入力します)entry 100%) 上端がスクロールポートを出るときに (まだ実行中であると仮定して) トリガーを解除します (exit 0%)。明確にするために、 entry 0% アニメーションがトリガーされるのは トップ エッジが入ります。 entry スクロールポートの下部からの要素を処理します。 exit 上部から処理します。ちょっとややこしいですが、あまり説明しなくてもわかりやすいと思います。
.square {
/* Declare animation */
animation: fade-bg-in 300ms;
/* Animation trigger conditions */
timeline-trigger: --trigger view() entry 100% exit 0%;
}
のために animation-triggerまず、どのトリガーについて話しているのかを指定し、次にいくつかの設定を宣言します (たとえば、 play-forwards):
.square {
/* Declare animation */
animation: fade-bg-in 300ms;
/* Animation trigger conditions */
timeline-trigger: --trigger view() entry 100% exit 0%;
/* Animation trigger settings */
animation-trigger: --trigger play-forwards;
}
play-forwards このキーワードは、正方形が完全に表示されるたびにアニメーションをトリガーします。アニメーションの塗りつぶしモードを ( を使用して) 宣言していないためです。 animation-fill-mode またはその一部として animation 略記)、クラスが後で背景を保持しないことを意味し、アニメーションはフラッシュのようなものです。
したがって、異なる結果を得るには、さらに追求する必要があります。
animation-fill-mode 対
まず、さまざまな塗りつぶしモードの値が何をするのかを要約します。 animation-fill-mode またはその一部として animation 略記:
forwards: : スタイルは保持されています 後 アニメーション。backwards: : スタイルが適用される 初め アニメーション。both: : どちらの実践も当てはまります。
さて、次のように仮定しましょう は play-forwards (前と同じように) フィルモードは forwards (both 不要でしょうから background 最初から設定されていません):
.square {
animation: fade-bg-in 300ms forwards;
timeline-trigger: --trigger view() entry 100% exit 0%;
animation-trigger: --trigger play-forwards;
}
これによりスタイルは保持されますが、クラスが部分的または完全にビューポートを出て再びビューポートに入ると、アニメーションが再開され、アニメーションの終了方法によってはフラッシュが発生する可能性があります。これがこの例で起こっていることです。
これを解決するには 2 つの異なる方法があります…
「ロックイン」方法: を使用します。 play-once の代わりに play-forwardsと組み合わせると forwards結果として得られるアニメーションは 1 回だけ実行され、再起動されることはなく、その後スタイルが保持されます。
.square {
/* Play once */
animation-trigger: --trigger play-once;
/* Retain the styles */
animation: fade-bg-in 300ms forwards;
timeline-trigger: --trigger view() entry 100% exit 0%;
}
「往復」方式: play-forwards play-backwards 完全に表示されている場合は要素を通常どおりアニメーション化し、完全に表示されていない場合は要素を反転します。要素は前方にアニメーションするのと同じくらいスムーズに後方にアニメーションするため、フラッシュはありません。さらに、アニメーションの方向が変わっても、塗りつぶしモードがオンのままになる場合があります。 forwards に設定される代わりに both。
なぜ?
play-forwards これは「アニメーションを 0% から 100% まで再生する」という意味です。 play-backwards これは「アニメーションを 100% から 0% まで再生する」という意味です。そんな中、先ほどもお話しましたが、 forwards フィル モードは、「アニメーションが完了してもスタイルを保持する」ことを意味します。これは、最後のキーフレームが 0% であるか 100% であるかには関係ありません。
.square {
/* Play forward and backward, as appropriate */
animation-trigger: --trigger play-forwards play-backwards;
/* Retain the styles either way */
animation: fade-bg-in 300ms forwards;
timeline-trigger: --trigger view() entry 100% exit 0%;
}
play-forwards、 play-onceそして play-backwards の唯一のキーワードではありません 。以下に簡単に説明します。
|
効果 |
|---|---|
none |
トリガーを条件付きで無効にする(開始時ではなく終了時は無効にする)(またはその逆)、または 1 つのトリガーで複数のトリガーを処理する animation-trigger |
play-forwards |
アニメーションを続行できるようにします |
play-backwards |
アニメーションを逆方向に再生できるようにします |
play-once |
前方または後方(どちらか早い方) |
play |
最後に指定した方向に移動するか、どちらも指定されていない場合は前方に移動します。 |
pause |
アニメーションを一時停止します |
reset |
アニメーションを停止し、進行状況を 0 に設定します。 |
replay |
進行状況を 0 に設定しますが、アニメーションは停止しません |
で これにより、スクロール時のアニメーションだけでなく、アクション、塗りつぶしモード、タイムライン範囲のさまざまな組み合わせ、および終了アニメーションをベイクできるという事実に対しても、かなりの量の制御が可能になります。 @keyframes ルールは、多くの場合、結果を達成するための複数の方法があることを意味します。
アニメーション アクション、フィル モード、タイムライン範囲などで構成されるスクロール トリガー アニメーションは過度に複雑に見えるかもしれませんが、これらのメカニズムが分離されているため、柔軟性を維持しながらロジックを再利用でき、繰り返しが減り、メカニズムの設計がよりシステムに適したものになります。
今回は 3 つのクラスを考えます。少し複雑にするために、次のように宣言します。 scale: 70% (アニメーション化する initial) を作成し、2 つの回転アニメーションを定義します。
/* Define animations */
@keyframes intensify {
to {
scale: initial;
background: currentColor;
}
}
@keyframes rotate-left {
to {
rotate: -5deg;
}
}
@keyframes rotate-right {
to {
rotate: 5deg;
}
}
.square {
/* Set starting value */
scale: 70%;
}
これはそれよりも似ており、明らかにより複雑な例ですが、値を短縮表現のプロパティにマージし、それらを短縮表現のプロパティに分離できること、およびさまざまなメカニズムの異なる性質により、柔軟性だけでなく再利用性も実現します (この場合、同じアニメーション トリガー設定を使用してさまざまなアニメーションをシリアル化します)。
.square {
/* Set starting value */
scale: 70%;
/* Define animation name */
--base-animation: intensify;
/* Declare animation */
animation: var(--base-animation) 300ms forwards;
/* Define animation trigger settings */
--animation-trigger: --trigger play-forwards play-backwards;
/* Declare for intensify, then for one of either rotate animations */
animation-trigger: var(--animation-trigger), var(--animation-trigger);
/* Declare animation trigger conditions (without timeline ranges) */
timeline-trigger: --trigger view();
/* Declare active range end */
timeline-trigger-active-range-end: normal;
/* Append other animations */
&.rotate-left {
animation-name: var(--base-animation), rotate-left;
}
&.rotate-right {
animation-name: var(--base-animation), rotate-right;
}
/* Stagger activation ranges */
&:first-child {
timeline-trigger-activation-range-start: entry 33.3333%;
}
&:nth-child(2) {
timeline-trigger-activation-range-start: entry 66.6666%;
}
&:last-child {
timeline-trigger-activation-range-start: entry 99.9999%;
}
}
ここでは、よりクリーンでより堅牢なバージョンが使用されています sibling-count() そして sibling-index() (Firefox はサポートされていません) アニメーションをシリアル化するには:
このバージョンでは、設定の代わりに、 timeline-trigger-activation-range-start それぞれのクラスで私たちはただ目標を達成します .square そして、即時のエントリ値を計算します。
/* Maximum entry ÷ number of squares */
--stagger-interval: calc(100% / sibling-count());
/* Current square’s index × stagger interval */
--entry: calc(sibling-index() * var(--stagger-interval));
/* Declare animation trigger conditions */
timeline-trigger: --trigger view() entry var(--entry) exit 0%;
要素を作成すると他の要素がトリガーされます
この場合、トリガーとその境界を最初の正方形に転送し、連続するアニメーションの遅延に従って他の正方形が続きます。ご覧のとおり、すべてのアニメーションがトリガーされます animation-trigger 最初のクラスの 50% が入場したら (entry 50%) ビューポート (view())。 animation-trigger によって引き起こされる timeline-trigger ダッシュアイデンティティ(適当な名前)なので --trigger) リンクします:
/* Define animations */
@keyframes intensify {
to {
scale: initial;
background: currentColor;
}
}
@keyframes rotate-left {
to {
rotate: -5deg;
}
}
@keyframes rotate-right {
to {
rotate: 5deg;
}
}
.square {
/* Set starting value */
scale: 70%;
/* Define animation name */
--base-animation: intensify;
/* Maximum delay ÷ number of squares */
--stagger-interval: calc(300ms / sibling-count());
/* Current square’s index × stagger interval */
--animation-delay: calc(sibling-index() * var(--stagger-interval));
/* Declare animation */
animation: var(--base-animation) 300ms var(--animation-delay) forwards;
/* Define animation trigger settings */
--animation-trigger: --trigger play-forwards play-backwards;
/* Declare for intensify, then for one of either rotate animations */
animation-trigger: var(--animation-trigger), var(--animation-trigger);
&:first-child {
/* Declare animation trigger conditions */
timeline-trigger: --trigger view() entry 50%;
/* Declare active range end */
timeline-trigger-active-range-end: normal;
}
/* Append other animations */
&.rotate-left {
animation-name: var(--base-animation), rotate-left;
}
&.rotate-right {
animation-name: var(--base-animation), rotate-right;
}
}
1 つの欠点は、次のような場合です。 animation-trigger いる play-backwards モード、アニメーションはブレません。これは、 私は思うアニメーションを反転すると遅延が追加されます。これは私には間違いのように思えます。特にそうではないからです。 animation-direction: reverseしかし、この点に関しては私は完全に間違っている可能性があります。
タイムラインの制限を理解する
タイムライン カテゴリはスクロール トリガー アニメーションの大部分を占めていますが、別のメカニズムです。スクロール用-ドリブン アニメーション、ご希望ですか animation-range そしてその長期特性。スクロール付き~刺激された アニメーションの構文は基本的に同じですが、異なるプロパティと 2 つの異なるカテゴリを使用します。アクティベーション エクステントはアニメーションがトリガーされるスクロール領域を決定し、アクティブ エクステントはアニメーションが (アクティベーション エクステントに存在しなくなった場合でも) 残る領域を決定します。
タイムラインの制限が少し重いです。しかし、 view() entry 100% exit 0% (完全に表示されている場合)および view() contain ほとんどの場合、(同じですがビューポートよりも大きい) で十分です。
しかし、もしあなたが飛び込む意欲があるなら、 animation-rangeただし、これはスクロール用です -ドリブン アニメーションは軽量で、初心者レベルでもタイムライン範囲を理解できます。その後、アニメーション トリガーの仕様を読んで、これらのスクロール トリガー アニメーションのコンテキストにおけるタイムライン範囲の多くの複雑さをカバーすることをお勧めします。
スクロール トリガー アニメーションの別の独立したコンポーネント view() 関数ですが、ここで要約する方が簡単です。基本的に、スクロールトリガーアニメーションに関しては、 view() ビューポートです。それで、あなたが持っているなら 5rem スティッキーヘッダー、 view(y 0 5rem) タイムライン範囲を Y 軸に沿って因数分解します。
最終的な考え
スクロールでトリガーされるアニメーションは、スクロール駆動のアニメーションに似ていますが、古い CSS 機能 (主に animation) およびメカニズムによるその他の新機能 (破線検出、 view()タイムライン範囲)、スクロール トリガー アニメーションに固有の CSS プロパティに加えて。一度にたくさんのことが起こっています。
正直に言うと、彼らについて自分がどのように感じているかはわかりません。それらは確かにクールで、楽しく、便利ですが、複雑でもあり、それらが何であるかを本当に理解し始めるまでにしばらく時間がかかりました。









Leave a Reply