スクロール駆動アニメーションは、ウェブでよく見られる UX パターンです。スクロール ドリブン アニメーションは、スクロール コンテナのスクロール位置にリンクされています。つまり、上下にスクロールすると、リンクされたアニメーションが前方または後方にスクラブされます。たとえば、スクロールに合わせて移動する視差効果のある背景画像や読書インジケーターなどがあります。
デベロッパーは通常、JavaScript を使用してメインスレッドのスクロール イベントに応答することで、スクロール駆動型アニメーションを作成してきました。スクロール イベントは非同期で配信されるため、スクロールと同期したパフォーマンスの高いスクロール ドリブン アニメーションを作成することが難しく、メインスレッドで実行されるため、ジャンクが発生することがよくあります。
しかし、ブラウザに導入される新しい CSS と UI の機能の一部として、宣言型のスクロールドリブン アニメーションを作成できるようになりました。Scroll Timelines と View Timelines は、既存の Web Animations API(WAAPI)と CSS Animations API と統合された新しいコンセプトです。これにより、わずか数行のコードで、メインスレッドから実行される滑らかなスクロール駆動型アニメーションを実現できます。このケーススタディでは、Tokopedia、redBus、Policybazaar がこの新機能をどのように活用しているかをご紹介します。
Tokopedia
Tokopedia は、以前のカスタム JavaScript 実装をスクロール駆動型アニメーションに置き換え、ページ パフォーマンスを最適化し、e コマース コンバージョン ファネル全体のブラウジング エクスペリエンスを向上させました。
従来の JavaScript スクロール イベントを使用した場合と比較して、コード行数を最大 80% 削減できました。また、スクロール中の平均 CPU 使用率が 50% から 2% に低下したことも確認できました。 Andy Wihalim、Tokopedia、シニア ソフトウェア エンジニア
コード
次の実装では、scroll() 関数を使用して、CSS アニメーションの進行状況を制御するための匿名のスクロール進行状況タイムラインを設定しています。上部の固定バーの表示 / 非表示は、定義された animationRange 内のスクロール位置に基づいて変化します。
const toggleBar = keyframes({
  to: { height: 48 },
});
export const cssWrapper = css({
  position: 'fixed',
  left: 0,
  width: '100vw',
  pointerEvents: 'none',
  marginTop: 120,
  height: 0,
  overflow: 'hidden',
  display: 'flex',
  flexDirection: 'column',
  justifyContent: 'flex-end',
  animation: `${toggleBar} linear both`,
  animationTimeline: 'scroll()',
  animationRange: '20px 70px',
});
redBus
redBus は、すべてのユーザーにコンバージョン ファネルの早い段階で表示されるアクティビティのランディング ページで、モバイルとパソコンで異なるアニメーションを使用しています。スクロールドリブン アニメーションを使用すると、これらのカスタム JavaScript 実装を CSS に置き換えて、同じ効果を実現できます。
ユースケース
Image Reveal(モバイル用)と Cover Flow(パソコン用)を備えたフォト ギャラリー。
コード(モバイル)
前の例では、Tokopedia は匿名のスクロール進行状況タイムラインを使用しました。次のコードでは、redBus は名前付きビュー進行状況タイムラインを使用しています。アニメーションは、要素の最も近い祖先スクローラ(この場合はフォト ギャラリーのスクローラ)内の定義された animation-range 内の <img> 要素の opacity と clip-path を変更します。
const reveal = keyframes`
   from {
       opacity: 0;
       clip-path: inset(45% 20% 45% 20%);
   }
   to {
       opacity: 1;
       clip-path: inset(0% 0% 0% 0%);
   }`
const CardImage = styled.div`
   width: 100%;
   height: 100%;
   img {
       border-top-left-radius: 0.75rem;
       border-top-right-radius: 0.75rem;
       height: 100%;
       width: 100%;
       object-fit: cover;
       view-timeline-name: --revealing-image;
       view-timeline-axis: block;
  
       /* Attach animation, linked to the  View Timeline */
       animation: linear ${reveal} both;
       animation-timeline: --revealing-image;
  
       /* Tweak range when effect should run*/
       animation-range: entry 25% cover 50%;
   }
`;
この機能は、パフォーマンスとユーザー エクスペリエンスの向上を両立させ、SEO のページ エクスペリエンス シグナルを強化するのに最適なため、非常に喜ばしいです。さらに、学習曲線が最小限であるため、すべての e コマース ウェブサイトに不可欠なツールとなっています。また、他のチームからも、SDA をより多くのユーザー ジャーニーに活用するための肯定的なフィードバックとサポートを得ています。」— Amit Kumar 氏、redBus シニア エンジニアリング マネージャー。
Policybazaar
保険プランの比較は、ユーザーが意思決定プロセスを導くために繰り返し行う重要なアクションです。Policybazaar は、スクロール駆動型アニメーションを使用して、ユーザーが表をスクロールしたときに優先度の低い要素のサイズを縮小しました。これにより、読みやすさを向上させながら、スムーズなスクロールを実現しました。
スクロール駆動型アニメーションにより、ユーザーがプランを比較するためのビューポートのスペースを最大限に確保し、集中してすっきりと読めるようにしました。- Rishabh Mehrotra(PolicyBazaar 生命保険 BU デザイン責任者)
animate-timeline を追加しました。コード
Tokopedia の前の例と同様に、Policybazaar は scroll() 関数を使用して、CSS アニメーションの進行状況を制御するための匿名のスクロール進行状況タイムラインを設定しています。この場合、定義された animation-range 内のスクロール位置に基づいて、フォントサイズを縮小し、ヘッダーをフェードアウトします。
@supports (animation-timeline: scroll()) {
.plan-comparison .inner-header {
animation: move-and-fade-header linear both;
}
.plan-comparison .left-side {
animation: shrink-name linear both;
}
.plan-comparison .inner-header, .plan-comparison .left-side {
animation-timeline: scroll();
animation-range: 0 150px;
}
}
@keyframes move-and-fade-header {
  to {
    translate: 0% -5%;
    top:103px;
}
}
@keyframes shrink-name {
  to {
    font-size: 1.5rem;
  }
}
ユーザー ジャーニー全体で共通のパターンとしてスクロール駆動型アニメーションを使用する
紹介した e コマース企業はすべて、カードを含むページでスクロール駆動型アニメーションを使用し、カードをアニメーション化してユーザーの注意を引いています。次の例は、ユーザー ジャーニーのさまざまな部分にあるカードのスクロール効果を示しています。通常、これは次の CSS スニペットに示すように、カスタム CSS アニメーションの進行状況を制御するために匿名のビュー進行状況タイムラインを使用して実現されます。
@keyframes animate-in {
 0% { opacity: 0; transform: translateY(10%); }
 100% { opacity: 1; transform: translateY(0); }
}
@keyframes animate-out {
 0% { opacity: 1; transform: translateY(0); }
 100% { opacity: 0; transform: translateY(-10%); }
}
.flyin_animate {
   animation: animate-in linear forwards;
   animation-timeline: view();
   animation-range: entry;
}
redBus(ホームページ)
Policybazaar(商品リスティング ページ)
Tokopedia(商品詳細ページ)
スクロール駆動型アニメーション API を使用する際の考慮事項
Scroll-timeline polyfill などを使用して、スクロール ドリブン アニメーションをサポートしていないブラウザ用にポリフィルすることができます。その場合は、フレームワークと連携して動作すること、ポリフィルを使用するブラウザでアニメーションの失敗やぎこちない動作が発生しないことを確認するために、追加のテストが必要になります。
CSS から @supports を使用して、スクロールドリブン アニメーションを使用する前に animation-timeline のサポートをテストできます。次に例を示します。
@supports (animation-timeline: scroll()) {
}
リソース
- スクロール駆動型アニメーションのデモ
 - スクロールドリブン アニメーションでスクロール時に要素をアニメーション化する
 - Codelab: CSS でスクロールドリブン アニメーションを使ってみる
 - Chrome 拡張機能: スクロール駆動型アニメーションのデバッガ
 - Scroll-timeline Polyfill
 - バグや新機能を報告しますか?皆様からのご意見をお待ちしております。
 
このシリーズの他の記事では、e コマース企業がビュー遷移、ポップオーバー、コンテナ クエリ、has() セレクタなどの新しい CSS 機能と UI 機能を使用して、どのようなメリットを得たかについて説明しています。