Back

ネイティブWeb APIでアニメーションライブラリを置き換える

ネイティブWeb APIでアニメーションライブラリを置き換える

ページ遷移、スクロールエフェクト、要素の登場アニメーションを処理するためだけにGSAPFramer MotionAnime.jsをプロジェクトにインポートしている場合、ブラウザがもはや必要としないバンドルの重さを抱えていることになります。モダンなWebアニメーションAPIは成熟し、日常的なUI作業のほとんどにおいて、JavaScriptアニメーションライブラリの置き換えが現実的な選択肢となっています。

プラットフォームが現在提供している機能を実践的に見ていきましょう。

重要なポイント

  • Web Animations API(Element.animate())は、ライブラリをインポートすることなくプログラマティックな制御(一時停止、再生、逆再生、シーク)を提供し、コンポジター対応プロパティをアニメーション化する際には、CSSアニメーションと同様にコンポジタースレッドで実行できます。
  • CSS Scroll-Driven Animationsを使用すると、アニメーションの進行状況をスクロール位置に直接紐付けることができ、Intersection Observer + アニメーションライブラリという一般的なパターンを純粋なCSSで置き換えられます。
  • View Transitions APIは、UI状態やページ間のアニメーション化された遷移を処理し、これまでFramer MotionのAnimatePresenceやカスタムGSAPタイムラインが必要だったユースケースをカバーします。
  • 物理ベースのモーション、複雑なSVG操作、高度なタイムラインオーケストレーションにおいては、ライブラリは依然としてその価値を発揮します。目標は、デフォルトではなく意図的にライブラリを選択することです。

Web Animations API:ライブラリなしでプログラマティック制御

Web Animations API(WAAPI)を使用すると、Element.animate()を使ってJavaScriptでDOM要素を直接アニメーション化できます。開発者が通常ライブラリに求める動的な制御(一時停止、再生、逆再生、シーク)を提供しながら、CSSアニメーションで使用されるのと同じブラウザアニメーションエンジンの恩恵を受けられます。

const card = document.querySelector('.card')
const animation = card.animate(
  [
    { transform: 'translateY(20px)', opacity: 0 },
    { transform: 'translateY(0)',    opacity: 1 }
  ],
  { duration: 400, easing: 'ease-out', fill: 'forwards' }
)

// 完了promiseを使ってアニメーションをチェーン
animation.finished.then(() => console.log('Entrance complete'))

delayによる段階的なアニメーション、.finishedによる連続的なチェーン、.playbackRateによる再生制御が、依存関係なしで実現できます。

置き換え対象: Anime.js、Velocity.js、基本的なGSAPのユースケース ブラウザサポート: すべてのモダンブラウザでサポートされています。現在の対応状況はcaniuse.comで確認できます。

アクセシビリティに関する注意: モーションを実行する前に必ずprefers-reduced-motionをチェックしてください。アニメーション呼び出し自体をスキップするのではなく、ユーザーがモーション削減を希望している場合はduration: 0を渡すことで、fill: 'forwards'によるレイアウトの副作用が引き続き適用されます。

const reduced = window.matchMedia('(prefers-reduced-motion: reduce)').matches
element.animate(keyframes, { duration: reduced ? 0 : 400, fill: 'forwards' })

CSS Scroll-Driven Animations:JavaScriptなしでスクロールエフェクト

CSS Scroll-Driven Animationsは、最も一般的なIntersection Observer + アニメーションライブラリのパターン、つまりユーザーがスクロールする際に要素を表示するパターンを置き換えます。

@keyframes fade-in {
  from { opacity: 0; transform: translateY(16px); }
  to   { opacity: 1; transform: translateY(0); }
}

.reveal {
  animation: fade-in linear both;
  animation-timeline: view();
  animation-range: entry 0% entry 40%;
}

JavaScriptもライブラリも不要です。ブラウザがアニメーションの進行状況を、スクロールコンテナ内の要素の位置に直接リンクします。

ブラウザサポート: Chrome 115以降のChromiumブラウザで提供され、各エンジンで進化を続けています。現在のサポート状況はcaniuse.comで確認してください。

View Transitions API:ページと状態の遷移

View Transitions APIは、2つのUI状態間のアニメーション化された遷移を処理します。これは以前、Framer MotionのAnimatePresenceやカスタムGSAPタイムラインが必要だったパターンです。

function navigate(updateFn) {
  if (!document.startViewTransition) {
    updateFn() // 未サポートブラウザ用のフォールバック
    return
  }
  document.startViewTransition(updateFn)
}

マルチページアプリケーションの場合、1つのCSSルールでドキュメント間遷移を有効化できます:

@view-transition {
  navigation: auto;
}

共有要素にview-transition-nameを割り当てると、ブラウザが自動的にページ間でモーフィングします。

ブラウザサポート: 同一ドキュメント遷移はモダンブラウザで広くサポートされており、ドキュメント間遷移は各エンジンで展開が続いています。現在の状況はcaniuse.comで確認してください。

置き換え対象: Framer Motionのページ遷移、React Routerアニメーションラッパー、カスタムGSAPページ切り替えロジック

ライブラリが依然として有効な場合

ネイティブAPIは日常的なアニメーションニーズの広範囲をカバーしますが、特定のシナリオではライブラリに明確な利点があります:

  • 物理ベースのモーション(スプリングアニメーション、モメンタム) — Framer Motion、React Spring
  • 複雑なSVGアニメーション — GSAPのMorphSVGやDrawSVGプラグイン
  • 高度なタイムラインオーケストレーション(多数の要素にまたがる)
  • 広範なクロスブラウザ抽象化(プログレッシブエンハンスメントに依存できない場合)

決定は「ネイティブ対ライブラリ」ではなく、プラットフォームがすでに特定の問題を解決しているかどうかです。

まとめ

アニメーション依存関係を追加する前に、Web Animations API、CSS Scroll-Driven Animations、またはView Transitions APIがユースケースをカバーしているかを確認してください。ほとんどの登場アニメーション、スクロールエフェクト、ページ遷移においては、これらで対応できます。ライブラリは、それらが真に優れている専門的な作業(物理ベースのスプリング、複雑なSVGモーフィング、複雑な多要素タイムライン)のために取っておきましょう。バンドルとユーザーの両方がその違いから恩恵を受けます。

よくある質問

シンプルな登場アニメーション、フェード、スライド、基本的なシーケンスについては、はい。GSAPは複雑なタイムラインオーケストレーション、MorphSVGなどのプラグインによるSVGモーフィング、物理ベースのエフェクトにおいて依然として優れています。GSAPの使用が不透明度とトランスフォームのトゥイーンに限定されている場合、Web Animations APIは同等のパフォーマンスでネイティブに処理できます。

スクロール駆動アニメーションはプログレッシブエンハンスメントとして扱ってください。CSSで要素をデフォルトで最終的な表示状態に設定し、その上にアニメーションを重ねます。サポートがないブラウザは、スクロールエフェクトなしでコンテンツを表示するだけです。コンテンツは完全にアクセス可能で読みやすい状態を保つため、JavaScriptフォールバックは不要です。

はい。シングルページアプリケーションの場合、状態更新関数をdocument.startViewTransition()内でラップします。Reactの場合、これはナビゲーションや状態変更ロジックの周りでstartViewTransitionを呼び出すことを意味します。フレームワーク統合はまだ進化中ですが、コアAPIは同期的にDOMを更新するか、flushSync経由で更新する任意のフレームワークで動作します。

はい。prefers-reduced-motionメディアクエリを尊重することは、ベストプラクティスでありアクセシビリティ要件でもあります。アニメーション呼び出し自体をスキップするのではなく、durationをゼロに設定してください。これにより、fill forwardsなどのプロパティによるレイアウトの副作用を保持しながら、一部のユーザーが混乱や害を感じる視覚的なモーションを削除できます。

Understand every bug

Uncover frustrations, understand bugs and fix slowdowns like never before with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data. Check our GitHub repo and join the thousands of developers in our community.

OpenReplay