CSSアニメーション完全ガイド ―
transition@keyframes を使いこなす

ボタンのhoverでふわっと変化する。ローディングアイコンがくるくる回る。ページを開いた瞬間にコンテンツがスッと現れる。すべてCSSだけで実現できます。JavaScriptなしで、ここまでできる。

transition と animation ― 何が違うのか

CSSでアニメーションを作る方法は、大きく分けて2つあります。transitionanimation@keyframes)です。似ているようで、役割はまったく異なります。

transition は「状態Aから状態Bへの変化を滑らかにするもの」。たとえばhoverしたときに色が変わる、フォーカスしたときに枠線が光る。きっかけ(トリガー)があって初めて動くのが特徴です。

一方、animation は「自分で動き続けるもの」。ページが読み込まれた瞬間から回転し続けるローディングスピナーや、ふわっと現れるフェードインがこちらに該当します。トリガーがなくても動かせる。さらに、途中で方向を変えたり、何段階もの変化を経る複雑な動きが作れます。

transition ― 状態変化をなめらかに
.button {
  background: #7c3aed;
  transition: background 0.3s ease;
}

.button:hover {
  background: #5b21b6;
}
animation ― 自律的に動き続ける
@keyframes spin {
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}

.spinner {
  animation: spin 1s linear infinite;
}
▶ Live Demo — transition vs animation
transition(hoverしてね)
animation(自動で回転)
📌 ポイント
「ユーザーの操作に反応する動き」なら transition、「自動的に再生される動き」なら animation。まずこの使い分けを意識するだけで、コードの設計がスッキリします。

transition を極める ― 4つのプロパティ

transition は実は4つのサブプロパティで構成されています。transition-property(何を)、transition-duration(何秒で)、transition-timing-function(どんなカーブで)、transition-delay(いつから)。ショートハンドで一括指定するのが一般的です。

transition ショートハンド
/* transition: [property] [duration] [timing] [delay] */

.card {
  transition: transform 0.3s ease;
  /* transform を 0.3秒で ease カーブで変化 */
}

/* 複数プロパティをアニメーションする場合 */
.card {
  transition: transform 0.3s ease,
              box-shadow 0.3s ease,
              opacity 0.3s ease;
}

イージング ― 動きの「質」を決める

transition-timing-function(イージング)は、アニメーションの「質」を決定づけるプロパティです。同じ0.3秒でも、easelinear ではまったく印象が変わります。現場で使い分けのポイントになるのは、「自然な動き」か「機械的な動き」か、という視点です。

▶ Live Demo — イージングの違いを比較(hoverで再生)
linear
ease
ease-in-out
bounce風

※ エリア全体にhoverすると全ボールが同時に動きます

💡 現場の経験則
UIの動きには easeease-in-out がほぼ万能です。linear はプログレスバーや回転など「機械的であるべき動き」に。cubic-bezier() で独自カーブを作ると、ブランドの個性が出ます。cubic-bezier.com で視覚的にカーブを調整できるので、ぜひ試してみてください。

実践:hoverで浮き上がるカード

現場で最もよく使う transition パターンのひとつが「hoverで浮き上がるカード」です。transform: translateY()box-shadow を組み合わせて、カードが少し持ち上がったような印象を作ります。

浮き上がるカードのCSS
.card {
  transition: transform 0.3s ease,
              box-shadow 0.3s ease;
}

.card:hover {
  transform: translateY(-6px);
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.12);
}
▶ Live Demo — hoverで浮き上がるカード
🎨
Design
💻
Code
🚀
Deploy

@keyframes の書き方と animation プロパティ

@keyframes を使うと、アニメーションの「台本」を自由に書けます。0%(from)から100%(to)までの間に、好きなだけ中間ステップを挟めるのが強みです。

@keyframes の基本構文
@keyframes fadeInUp {
  0% {
    opacity: 0;
    transform: translateY(30px);
  }
  100% {
    opacity: 1;
    transform: translateY(0);
  }
}

.element {
  animation: fadeInUp 0.6s ease forwards;
}

animation プロパティも transition と同様にショートハンドがあります。順番は namedurationtiming-functiondelayiteration-countdirectionfill-mode。全部覚える必要はなく、よく使うパターンを押さえておけば十分です。

よく使うアニメーションパターン集

▶ Live Demo — 定番パターン4選
spin
pulse
bounce
shake
上の4パターンの @keyframes
/* 回転 */
@keyframes spin {
  to { transform: rotate(360deg); }
}

/* 脈動 */
@keyframes pulse {
  0%, 100% { transform: scale(1); }
  50%       { transform: scale(1.15); }
}

/* バウンド */
@keyframes bounce {
  0%, 100% { transform: translateY(0); }
  50%       { transform: translateY(-16px); }
}

/* 揺れ */
@keyframes shake {
  0%, 100% { transform: translateX(0); }
  25%       { transform: translateX(-6px); }
  75%       { transform: translateX(6px); }
}

ローディングスピナーを作ってみよう

実務でCSSアニメーションが活躍する代表的な場面が、ローディングスピナーです。外部ライブラリに頼らなくても、CSSだけで十分美しいスピナーが作れます。

リングスピナーのCSS
@keyframes ring-spin {
  to { transform: rotate(360deg); }
}

.spinner {
  width: 48px;
  height: 48px;
  border: 4px solid #e9d5ff;
  border-top-color: #7c3aed;
  border-radius: 50%;
  animation: ring-spin 0.8s linear infinite;
}
▶ Live Demo — 3種のローディングスピナー
ring
dual ring
dots
💡 現場の経験則
ドットスピナーの animation-delay をずらす手法は、「波のような動き」を作る万能テクニックです。要素を複数並べて少しずつディレイをずらすだけで、ウェーブ、カスケード、タイピングなど、さまざまな表現ができます。

アクセシビリティ ― prefers-reduced-motion

アニメーションはUIを魅力的にしますが、すべての人にとって快適とは限りません。前庭機能障害のある方や、動きに酔いやすい方にとって、過度なアニメーションは深刻な問題になることがあります。

CSSには prefers-reduced-motion というメディアクエリがあり、ユーザーがOSの設定で「視覚効果を減らす」を有効にしている場合に、アニメーションを抑制できます。これは「配慮」ではなく「設計」として組み込むべきものです。

✅ アクセシビリティ対応の定番パターン
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}
❌ アニメーションを完全に消す(推奨しない)
/* animation: none だと fill-mode の状態も消えてレイアウト崩れの原因に */
@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; }
}
⚠️ 注意
animation: none ではなく animation-duration: 0.01ms にする理由は、animation-fill-mode: forwards で最終状態を保持している場合に、none だとその状態も消えてしまうためです。極小のdurationに設定することで、アニメーション自体は「実行済み」として最終状態を保持できます。

まとめ

  • transition は「状態AからBへの変化を滑らかにする」もので、hover やクラス変更などのトリガーが必要です
  • animation(@keyframes)は「自律的に動く」もので、ループや複雑な多段階の動きを表現できます
  • イージング(timing-function)がアニメーションの印象を決めます。UIにはease系、機械的な動きにはlinearが基本です
  • hoverカードの浮き上がり表現は、translateY + box-shadow の transition で簡単に実現でき、現場での出番が非常に多いパターンです
  • ローディングスピナーはCSSだけで作れます。animation-delay をずらすテクニックで、波打つような動きも表現可能です
  • prefers-reduced-motion への対応は必須です。animation-duration を極小値に設定する手法で、fill-mode の状態を維持しながらアニメーションを抑制できます