mcpField
C
css-animations

css-animations

github.com/chanjing-aiクリエイティブ・メディア0182 回インストール14 週間前に更新
リポジトリ

css-animations について

FrameVideo の動画合成で、CSS キーフレームアニメーションをシーク可能にするスキルです。装飾や単純な有限アニメーションに適し、複数要素の精密な演出には GSAP を使います。

主な機能

  1. 01CSS キーフレームのシーク
  2. 02有限な装飾ループの作成
  3. 03要素ごとの入場モーション
  4. 04GSAP との併用
  5. 05タイミングと描画の検証

活用シーン

  1. 01合成にシマーやグローを追加
  2. 02ロゴにパルスを付ける
  3. 03要素ごとの入場演出を作成

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/chanjing-ai/framevideo --skill css-animations

インストール後、Claude Code で/css-animationsを入力して読み込まれたか確認します。

詳細

FrameVideo の CSS アニメーション

FrameVideo は、css ランタイムアダプターを通じて CSS キーフレームアニメーションをシークできます。シンプルな繰り返しモチーフ、背景の動き、シマー、グロー、マスク、シーケンス化されない装飾に使用してください。

シーンの演出には、通常 GSAP のほうがわかりやすくなります。CSS アニメーションは、動きが 1 つの要素に属し、期間が固定されている場合に最適です。

使用する場面

CSS アニメーションは、次の用途に使用してください。

  • 装飾レイヤー — 背景パターン、シマー効果、グレイン、厳密なタイミングを必要としない控えめなパララックス
  • シンプルなループ — 繰り返し回数が決まっているパルス、グロー、呼吸のような効果
  • 要素ごとの動き — 各要素が個別にアニメーションする登場アニメーション
  • 依存関係のない動き — GSAP やその他のライブラリを読み込まずにアニメーションさせたい場合
  • GPU アクセラレーション効果 — ブラウザーが自動的に最適化する transform と opacity のアニメーション

使用しないでください

次の用途では CSS アニメーションを避けてください。

  • シーンの演出 — 厳密なタイミングが必要な複数要素のシーケンス → gsap を使用してください
  • 複雑なタイムライン — 一時停止/再開の制御や動的な期間が必要なもの → gsap を使用してください
  • 無限ループ — ブラウザーがシーク可能な WAAPI ハンドルを公開することを確認できている場合を除きます(ヘッドレスレンダーではまれです)
  • インタラクティブなアニメーション — ホバー、スクロール、ユーザー操作で開始する動きは、決定論的にレンダリングされません
  • レイアウトアニメーション — top、left、width、height のアニメーションはリフローを発生させます → 代わりに transform を使用してください

契約

  • ランタイムの初期化が完了する前に、アニメーションする要素を DOM に配置してください。
  • 時間指定のある要素には data-start の値を設定し、ローカルのアニメーション時間をクリップに合わせてください。
  • WAAPI による CSS アニメーションが利用できない環境では、負の delay によるフォールバックで無制限の期間を表現できないため、有限の animation-duration と animation-iteration-count を使用してください。
  • シークした状態がアニメーションの前後で維持されるよう、animation-fill-mode: both を推奨します。
  • 実時間に依存する JavaScript、ホバーでトリガーされる状態、ユーザーイベントに依存するクラスの切り替えは避けてください。

アダプターは、計算済みの animation-name を持つ要素を検出し、利用可能な場合はブラウザーの Animation ハンドルをシークします。利用できない場合は、負の animation-delay を設定して一時停止します。

基本パターン

<div
  id="pulse-ring"
  class="clip pulse-ring"
  data-start="0"
  data-duration="4"
  data-track-index="2"
></div>

<style>
  .pulse-ring {
    width: 280px;
    height: 280px;
    border: 4px solid rgba(255, 255, 255, 0.7);
    border-radius: 50%;
    animation-name: pulse-ring;
    animation-duration: 1200ms;
    animation-timing-function: cubic-bezier(0.2, 0, 0, 1);
    animation-iteration-count: 3;
    animation-fill-mode: both;
  }

  @keyframes pulse-ring {
    from {
      opacity: 0;
      transform: scale(0.82);
    }
    35% {
      opacity: 1;
    }
    to {
      opacity: 0;
      transform: scale(1.18);
    }
  }
</style>

スタッガーパターン

キーフレームの重複を避けるには、CSS カスタムプロパティを使用してください。

<div class="clip dots" data-start="1" data-duration="3" data-track-index="3">
  <span style="--i: 0"></span>
  <span style="--i: 1"></span>
  <span style="--i: 2"></span>
</div>

<style>
  .dots span {
    display: inline-block;
    width: 18px;
    height: 18px;
    margin-right: 10px;
    border-radius: 50%;
    background: currentColor;
    animation: dot-pop 900ms ease-out both;
    animation-delay: calc(var(--i) * 120ms);
  }

  @keyframes dot-pop {
    from {
      opacity: 0;
      transform: translateY(18px) scale(0.75);
    }
    to {
      opacity: 1;
      transform: translateY(0) scale(1);
    }
  }
</style>

適した用途

  • 繰り返し回数が決まっている装飾的なループ。
  • マスク、グロー、シマー、グレイン、控えめなパララックスレイヤー。
  • 完全な JS タイムラインを用意するほどではない、シンプルな 1 要素の登場アニメーション。

GSAP との組み合わせ

CSS アニメーションと GSAP タイムラインは、同じコンポジション内で共存できます。それぞれの役割は次のとおりです。

CSS が担当する装飾:

  • 背景パターン、グレイン、ノイズ
  • アンビエントグロー、シマー、パルス効果
  • マスクによる表示、ビネット
  • 控えめな環境の動き(浮遊するパーティクル、ゆっくりしたドリフト)

GSAP が担当する演出:

  • キャプションのタイミングとシーケンス
  • シーン遷移とクロスフェード
  • 音声に合わせた UI 要素の登場
  • 厳密に制御する複数要素のスタッガー
同期パターン

CSS アニメーションのタイミングは、クリップの data-start に合わせます。

<div class="clip bg-shimmer" data-start="0" data-duration="10">
  
</div>

<script>
  const tl = gsap.timeline();
  tl.to("#caption-1", { opacity: 1, duration: 0.5 }, 2);
  tl.to("#caption-2", { opacity: 1, duration: 0.5 }, 5);
  // GSAP controls captions, CSS handles background
</script>

CSS アダプターと GSAP アダプターは独立して動作しますが、どちらも FrameVideo のグローバルタイムラインに従うため、プレビューとレンダーの両方で同期が保たれます。

高度なパターン

カスタムプロパティを使った複雑なスタッガー

データ属性や計算値に基づいてスタッガーさせる場合:

<div class="grid">
  <div class="cell" style="--row: 0; --col: 0"></div>
  <div class="cell" style="--row: 0; --col: 1"></div>
  
</div>

<style>
  .cell {
    animation: cell-reveal 600ms ease-out both;
    animation-delay: calc((var(--row) * 3 + var(--col)) * 80ms);
  }

  @keyframes cell-reveal {
    from { opacity: 0; transform: scale(0.8); }
    to { opacity: 1; transform: scale(1); }
  }
</style>
無限に見えるパターンの有限ループ

パターンを無限に見せつつ、レンダリング時には有限にする場合:

.background-drift {
  /* Appears infinite but is actually 50 iterations over 100s */
  animation: drift 2000ms linear 50;
}

@keyframes drift {
  from { transform: translateX(0); }
  to { transform: translateX(-100px); }
}

ルール: 繰り返し回数 = クリップの期間 / アニメーションの期間 を計算し、切り上げます。2 秒のアニメーションを 30 秒のクリップで使用する場合は、animation-iteration-count: 15 です。

アニメーションの連鎖

1 つの要素で複数のアニメーションを順番に実行します。

.logo {
  animation: 
    fade-in 800ms ease-out 0s both,
    pulse 1200ms ease-in-out 1s 3 both,
    fade-out 800ms ease-in 4.6s both;
}

@keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes pulse { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.05); } }
@keyframes fade-out { from { opacity: 1; } to { opacity: 0; } }

delay は累積します。フェードインは 0 秒、パルスは 1 秒、フェードアウトは 4.6 秒に開始します。

パフォーマンスの最適化
.optimized {
  /* Tell browser to promote to GPU layer */
  will-change: transform, opacity;
  
  /* Prefer transform over position */
  animation: slide-in 600ms ease-out both;
}

@keyframes slide-in {
  /* Good: GPU-accelerated */
  from { transform: translateX(-100px); opacity: 0; }
  to { transform: translateX(0); opacity: 1; }
  
  /* Avoid: causes reflow */
  /* from { left: -100px; } to { left: 0; } */
}

可能な場合は transform と opacity のみをアニメーションしてください。width、height、top、left、margin、padding は避けてください。

パフォーマンス比較

指標CSS アニメーションGSAPWAAPIAnime.js
バンドルサイズ0 KB45 KB0 KB17 KB
初期化時間0 ms8 ms0 ms4 ms
シーク性能⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
GPU アクセラレーション自動手動自動手動
最適な用途装飾シーケンス軽量コンパクト

CSS のほうが高速な場合:

  • シンプルなループ(パルス、グロー、回転)
  • GPU アクセラレーション対応のプロパティのみ(transform、opacity)
  • タイムライン制御が不要な場合

GSAP のほうが高速な場合:

  • 10 個以上のトゥイーンを含む複雑なシーケンス
  • 正確なタイミング制御とラベル
  • 動的な再生時間または再生速度
  • ネストされたタイムライン

避けるべきこと

  • ブラウザーがシーク可能な WAAPI ベースの CSS アニメーションハンドルを公開していると確認できていない限り、無限 CSS アニメーションは避けてください。表示時間をカバーする有限の反復回数を指定してください。
  • transform で対応できる場合に、top、left、width、height などのレイアウトプロパティをアニメーションさせること。
  • ホバー、フォーカス、スクロール、メディアクエリーを使って、レンダリングに不可欠なモーションをトリガーすること。
  • 起動後にアニメーションクラスを変更すること。ただし、その変更を別の決定論的なタイムラインで制御する場合を除きます。

検証

CSS アニメーションの構成を編集した後:

npx framevideo lint      # Check timing contract
npx framevideo validate  # Check runtime errors

手動チェック:

  1. シークテスト — プレビューのタイムラインをスクラブし、アニメーションが各フレームで保持されることを確認します
  2. 反復回数 — animation-iteration-count がクリップの再生時間をカバーしていることを確認します(最後に空白のフレームがないこと)
  3. フィルモード — animation-fill-mode: both を確認し、シークした状態が前後で保持されるようにします
  4. GPU レイヤー — DevTools の Performance を開いてレンダリングを記録し、レイアウトの頻繁な再計算がないことを確認します

実例

例 1:背景のシマー

ユースケース: アニメーションライブラリを読み込まずに、製品カードの背景に控えめなシマーを追加します。

<div class="clip product-card" data-start="0" data-duration="5">
  <div class="shimmer-layer"></div>
  <h2>Product Name</h2>
</div>

<style>
  .shimmer-layer {
    position: absolute;
    inset: 0;
    background: linear-gradient(90deg, transparent, rgba(255,255,255,0.2), transparent);
    animation: shimmer 2s linear infinite;
  }
  @keyframes shimmer {
    from { transform: translateX(-100%); }
    to { transform: translateX(100%); }
  }
</style>

結果: 滑らかなシマー効果、オーバーヘッド 0 KB、GPU アクセラレーション対応。

例 2:ローディングドット

ユースケース: 構成のビルド中に表示するアニメーション付きのローディングインジケーター。

<div class="dots">
  <span style="--i: 0"></span>
  <span style="--i: 1"></span>
  <span style="--i: 2"></span>
</div>

<style>
  .dots span {
    animation: dot-bounce 1.4s ease-in-out infinite both;
    animation-delay: calc(var(--i) * 160ms);
  }
  @keyframes dot-bounce {
    0%, 80%, 100% { transform: scale(0); }
    40% { transform: scale(1); }
  }
</style>

結果: CSS のみでずらした、クラシックな3つのドットのアニメーション。

例 3:ロゴのパルスリング

ユースケース: パルスするリング効果でロゴを目立たせます。

<div class="clip logo-intro" data-start="0" data-duration="4">
  <div class="logo-container">
    <img src="logo.svg" alt="Logo">
    <div class="pulse-ring"></div>
  </div>
</div>

<style>
  .pulse-ring {
    position: absolute;
    inset: -20px;
    border: 3px solid rgba(255,255,255,0.6);
    border-radius: 50%;
    animation: pulse 1.5s cubic-bezier(0.2, 0, 0, 1) 2 both;
  }
  @keyframes pulse {
    from { opacity: 0; transform: scale(0.8); }
    35% { opacity: 1; }
    to { opacity: 0; transform: scale(1.2); }
  }
</style>

結果: ロゴの周囲に2つのリングが広がり、アニメーション全体の長さは3sです。

クレジットと参考資料

コメント