CSS REFERENCE

インタラクティブ

animation 要素

ー @keyframes と組み合わせて、自発的に動き続けるアニメーションを作る

POINT !

animation 要素のポイント!

  • animation は transition と異なり、外部トリガー不要で「自発的に動き続ける」アニメーションを実現する。@keyframes でアニメーションの「型(振り付け)」を定義し、animation プロパティで要素に適用するという2ステップが基本構造。
  • animation-fill-mode: forwards は「アニメーション終了後に最終フレームの状態を維持する」設定。ページ読み込み時のフェードイン演出では必須。省略すると要素が元の状態に戻ってしまう。
  • animation-delay を各要素で少しずつずらすことで、複数要素が「順番に登場する」スタッガーアニメーションが実現できる。:nth-child() セレクタとの組み合わせが定番パターン。
  • animation-play-state: paused を使うと、JavaScript や :hover でアニメーションを一時停止・再開できる。無限ループアニメーションをインタラクティブに制御する際に有効。

概要

animation プロパティは、@keyframes ルールと組み合わせることで、CSS だけで複雑かつ自律的なアニメーションを実現するためのプロパティです。

@keyframes では 0%(from)〜 100%(to)の間に任意の数のキーフレームを設定でき、各フレームでの CSS スタイルを定義します。animation プロパティは、その「振り付け」を実際の要素に「何秒で」「何回」「どの方向に」再生するかを指示します。

transition との本質的な違いは「自律性」にあります。
・transition → 外部トリガー(hover など)が必要、A→B の1回の変化
・animation → トリガー不要で自発的に動き、ループや逆再生も可能

animation は以下のサブプロパティで構成されます。
・animation-name:@keyframes の名前
・animation-duration:1サイクルの時間(必須)
・animation-timing-function:イージング
・animation-delay:開始遅延
・animation-iteration-count:繰り返し回数(infinite で無限)
・animation-direction:再生方向(normal / reverse / alternate)
・animation-fill-mode:開始前・終了後の状態
・animation-play-state:再生 / 一時停止

ローディングスピナー、パルス演出、ページ入場アニメーションなど、UI の「鼓動」を作り出す最も重要な CSS の仕組みのひとつです。

具体的な役割

ページ読み込み時のコンテンツ入場演出(fadeInUp)、ローディングスピナー、通知バッジのパルス、スケルトンスクリーンのシマー効果、背景グラデーションのゆらぎなど「自発的に動き続ける演出」に使う。

アクセシビリティ

♿ animation は視覚的に強い刺激を与えるため、アクセシビリティへの配慮が特に重要です。

前庭障害のあるユーザーは、激しく動くアニメーションで吐き気や頭痛を感じる場合があります。
必ず @media (prefers-reduced-motion: reduce) ブロックで、アニメーションを無効化または大幅に抑制してください。

具体的な対応パターン:
・infinite のアニメーションは完全に停止(animation: none)
・入場アニメーションは opacity のみの変化に留める
・duration を極端に長くして実質的に止める

また、点滅(blink)アニメーションは光感受性てんかんのリスクがあり、1秒に3回以上の点滅は WCAG 2.1 のガイドラインで禁止されています。

セットで使うプロパティ

📦 animation を設定した要素は、@keyframes で定義されたスタイルをフレームごとに適用されます。

【@keyframes との関係】
@keyframes には グローバルスコープで名前をつけて定義し、animation-name で参照します。同名の @keyframes が複数あった場合、後から定義されたものが優先されます。

【複数アニメーションの同時適用】
カンマ区切りで複数の animation を同じ要素に適用できます。
example: animation: fadeIn 0.5s ease, float 3s ease-in-out infinite

【パフォーマンス】
transition 同様、transform と opacity のアニメーションが GPU 加速の恩恵を受けます。width や height を@keyframesで変化させるとレイアウト再計算(reflow)が発生するため注意が必要です。

技術の変遷:昔の常識 vs 今の常識

TRADITION (昔)
JavaScript の setInterval でスタイルを書き換えるアニメーション、または GIF 画像でアニメーションを表現していた。GIF はファイルサイズが大きく色数制限もあり、JavaScript アニメーションはスクロールや他の処理と競合してカクつく問題があった。
MODERN (今)
CSS animation + @keyframes が主流。JavaScript で細かく制御が必要な場合は Web Animations API(element.animate())を使う。複雑なシーケンスアニメーションには GSAP などのライブラリも選択肢。prefers-reduced-motion による配慮は必須。

関連する値

値 / 関連 説明
animation-name @keyframes で定義した名前を指定。none を指定するとアニメーションなし
animation-duration 1サイクルにかかる時間(s / ms)。省略すると 0s でアニメーションが見えない
animation-iteration-count 繰り返し回数。infinite で無限ループ。小数も可(0.5 で半サイクル)
animation-fill-mode none(デフォルト)/ forwards(終了後に最終フレームを維持)/ backwards(遅延中に最初のフレームを適用)/ both
animation-direction normal(デフォルト)/ reverse(逆再生)/ alternate(往復)/ alternate-reverse(逆から往復)
animation-play-state running(デフォルト)/ paused(一時停止)。JavaScript や :hover での動的制御に使う
継承 なし
初期値 none 0s ease 0s 1 normal none running

利用例

ページ入場アニメーション(スタッガー)

複数カードが順番にふわっと登場する演出。animation-delay を :nth-child でずらすスタッガーパターン。

HTML Structure
<style>@keyframes fadeInUp{from{opacity:0;transform:translateY(24px)}to{opacity:1;transform:translateY(0)}}.card{opacity:0;animation:fadeInUp 0.6s ease-out forwards;background:white;border-radius:10px;padding:18px;box-shadow:0 2px 8px rgba(0,0,0,0.08);display:flex;align-items:center;gap:14px}.card:nth-child(1){animation-delay:0s}.card:nth-child(2){animation-delay:0.15s}.card:nth-child(3){animation-delay:0.3s}</style><div style="padding:24px;background:#f1f5f9;border-radius:12px;display:flex;flex-direction:column;gap:12px"><div class="card"><span style="font-size:28px">🎨</span><div><div style="font-weight:700;font-size:14px">デザイン</div><div style="font-size:12px;color:#64748b">UIの美しさを作る</div></div></div><div class="card"><span style="font-size:28px">💻</span><div><div style="font-weight:700;font-size:14px">開発</div><div style="font-size:12px;color:#64748b">コードで形にする</div></div></div><div class="card"><span style="font-size:28px">🚀</span><div><div style="font-weight:700;font-size:14px">リリース</div><div style="font-size:12px;color:#64748b">世界に届ける</div></div></div></div>
CSS Style
@keyframes fadeInUp {
  from {
    opacity: 0;
    transform: translateY(24px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.card {
  opacity: 0; /* 初期状態を非表示に */
  animation: fadeInUp 0.6s ease-out forwards;
}

/* 各カードの遅延をずらす */
.card:nth-child(1) { animation-delay: 0s; }
.card:nth-child(2) { animation-delay: 0.1s; }
.card:nth-child(3) { animation-delay: 0.2s; }
.card:nth-child(4) { animation-delay: 0.3s; }

@media (prefers-reduced-motion: reduce) {
  .card {
    animation: none;
    opacity: 1;
  }
}

ローディングスピナーとスケルトンスクリーン

infinite アニメーションの2大定番パターン。スピナーは rotate、スケルトンはグラデーションのスライドで実装。

HTML Structure
<style>@keyframes spin{to{transform:rotate(360deg)}}@keyframes shimmer{from{background-position:-200% 0}to{background-position:200% 0}}.spinner{width:40px;height:40px;border:3px solid #e2e8f0;border-top-color:#1a56db;border-radius:50%;animation:spin 0.8s linear infinite}.skeleton{background:linear-gradient(90deg,#f1f5f9 25%,#e2e8f0 50%,#f1f5f9 75%);background-size:200% 100%;animation:shimmer 1.5s infinite;border-radius:6px}</style><div style="padding:28px;background:white;border-radius:12px;display:flex;flex-direction:column;gap:24px"><div style="display:flex;align-items:center;justify-content:center;padding:20px"><div class="spinner"></div></div><div style="display:flex;align-items:center;gap:14px;padding:16px;background:#f8fafc;border-radius:10px"><div class="skeleton" style="width:48px;height:48px;border-radius:50%;flex-shrink:0"></div><div style="flex:1;display:flex;flex-direction:column;gap:8px"><div class="skeleton" style="height:14px;width:60%"></div><div class="skeleton" style="height:12px;width:40%"></div></div></div></div>
CSS Style
/* スピナー */
@keyframes spin {
  to { transform: rotate(360deg); }
}

.spinner {
  width: 40px;
  height: 40px;
  border: 3px solid #e2e8f0;
  border-top-color: #1a56db;
  border-radius: 50%;
  animation: spin 0.8s linear infinite;
}

/* スケルトンスクリーン */
@keyframes shimmer {
  from { background-position: -200% 0; }
  to   { background-position:  200% 0; }
}

.skeleton {
  background: linear-gradient(
    90deg,
    #f1f5f9 25%,
    #e2e8f0 50%,
    #f1f5f9 75%
  );
  background-size: 200% 100%;
  animation: shimmer 1.5s infinite;
  border-radius: 6px;
}

よくある誤用・注意点

animation-fill-mode を省略して opacity: 0 から始まるアニメーションを作ると、終了後に要素が消えて見えなくなる。また、初期状態と @keyframes の 0% が食い違うと、アニメーション開始時に一瞬「パチッ」とジャンプする現象が起きる。

HTML Structure
CSS (Incorrect)
/* ❌ 悪い例:fill-mode 省略で要素が消える */
.card {
  opacity: 0;
  animation: fadeIn 0.5s ease;
  /* forwards を付けないと終了後に opacity: 0 に戻る */
}

@keyframes fadeIn {
  to { opacity: 1; }
}

/* ❌ 悪い例:from の定義と初期スタイルが食い違う */
.box {
  opacity: 1; /* 初期値は1 */
  animation: appear 0.5s ease forwards;
}
@keyframes appear {
  from { opacity: 0; } /* 0から始まるため開始時にパチッとジャンプ */
  to   { opacity: 1; }
}

/* ✅ 良い例:初期状態と from を一致させ fill-mode を明示 */
.box {
  opacity: 0; /* 初期値を from に合わせる */
  animation: appear 0.5s ease forwards;
}
@keyframes appear {
  from { opacity: 0; }
  to   { opacity: 1; }
}