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

transition と animation ― 何が違うのか
CSSでアニメーションを作る方法は、大きく分けて2つあります。transition と animation(@keyframes)です。似ているようで、役割はまったく異なります。
transition は「状態Aから状態Bへの変化を滑らかにするもの」。たとえばhoverしたときに色が変わる、フォーカスしたときに枠線が光る。きっかけ(トリガー)があって初めて動くのが特徴です。
一方、animation は「自分で動き続けるもの」。ページが読み込まれた瞬間から回転し続けるローディングスピナーや、ふわっと現れるフェードインがこちらに該当します。トリガーがなくても動かせる。さらに、途中で方向を変えたり、何段階もの変化を経る複雑な動きが作れます。
.button {
background: #7c3aed;
transition: background 0.3s ease;
}
.button:hover {
background: #5b21b6;
}
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
.spinner {
animation: spin 1s linear infinite;
}
transition を極める ― 4つのプロパティ
transition は実は4つのサブプロパティで構成されています。transition-property(何を)、transition-duration(何秒で)、transition-timing-function(どんなカーブで)、transition-delay(いつから)。ショートハンドで一括指定するのが一般的です。
/* 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秒でも、ease と linear ではまったく印象が変わります。現場で使い分けのポイントになるのは、「自然な動き」か「機械的な動き」か、という視点です。
※ エリア全体にhoverすると全ボールが同時に動きます
実践:hoverで浮き上がるカード
現場で最もよく使う transition パターンのひとつが「hoverで浮き上がるカード」です。transform: translateY() と box-shadow を組み合わせて、カードが少し持ち上がったような印象を作ります。
.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);
}
@keyframes の書き方と animation プロパティ
@keyframes を使うと、アニメーションの「台本」を自由に書けます。0%(from)から100%(to)までの間に、好きなだけ中間ステップを挟めるのが強みです。
@keyframes fadeInUp {
0% {
opacity: 0;
transform: translateY(30px);
}
100% {
opacity: 1;
transform: translateY(0);
}
}
.element {
animation: fadeInUp 0.6s ease forwards;
}
animation プロパティも transition と同様にショートハンドがあります。順番は name、duration、timing-function、delay、iteration-count、direction、fill-mode。全部覚える必要はなく、よく使うパターンを押さえておけば十分です。
よく使うアニメーションパターン集
/* 回転 */
@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だけで十分美しいスピナーが作れます。
@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;
}
アクセシビリティ ― 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; }
}
まとめ
- 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 の状態を維持しながらアニメーションを抑制できます