CSSアニメーションの作り方|@keyframesとanimationプロパティの基本
WebページにCSSだけでアニメーションを付けたいとき、JavaScriptは不要です。@keyframes と animation プロパティを組み合わせるだけで、フェードイン・スライド・バウンスなど多彩な動きが作れます。
@keyframes の書き方
@keyframes はアニメーションの「コマ」を定義するルールです。from(0%)と to(100%)で開始・終了状態を指定するか、パーセントで細かく中間状態を指定できます。
| 記法 | 意味 |
|---|---|
from { } to { } | 0%から100%への2点指定(シンプルな場合に向く) |
0% { } 50% { } 100% { } | 中間状態を含む多点指定 |
animation プロパティ(ショートハンド)
animation は複数のサブプロパティをまとめて書けます。順番は以下の通りです。
| 位置 | サブプロパティ | 例 |
|---|---|---|
| 1 | animation-name | fadeIn |
| 2 | animation-duration | 0.6s |
| 3 | animation-timing-function | ease |
| 4 | animation-delay | 0.2s |
| 5 | animation-iteration-count | 1 / infinite |
| 6 | animation-direction | normal / alternate |
よく使うアニメーションのCSS例
実際の現場でよく使うパターンを3つ紹介します。
① フェードイン
要素が透明から不透明になるもっともシンプルなアニメーションです。
- ページ読み込み時のコンテンツ表示に定番
opacityの変化だけで実装できる
② スライドアップ
下から上にスライドしながらフェードインします。モーダルやカードの登場演出に向きます。
transform: translateY()とopacityを組み合わせるease-outを使うと自然な減速感が出る
③ バウンス
上下に弾むアニメーションです。ボタンや通知バッジに使うと注目を集めます。
animation-direction: alternate+animation-iteration-count: infiniteでループできる
タイミング関数(easing)の選び方
| 値 | 動き方 | 向く用途 |
|---|---|---|
ease | ゆっくり始まり中盤速くなり減速 | 汎用(デフォルト) |
ease-out | 速く始まり減速して止まる | スライドイン・フェードイン |
ease-in | ゆっくり始まり加速して終わる | スライドアウト・消える演出 |
linear | 一定速度 | スピン・ローダー |
ease-in-out | 両端ゆっくり中央速い | 行き帰り対称の動き |
CSSアニメーションジェネレーターを使えば6種のプリセットをスライダーで調整してすぐコピーできます。設定値を変えながらプレビューで確認できるので、コードを書く前に動きを確かめたいときに便利です。
滑らかに動かすために変えるべきプロパティ
アニメーションのカクつきは、多くの場合「動かしているプロパティ」が原因です。width・height・top・left を変化させると、ブラウザはレイアウトを計算し直します。これが毎フレーム発生すると処理が追いつきません。
| 動かすもの | 発生する処理 | 負荷 |
|---|---|---|
| transform / opacity | 合成のみ | 軽い(推奨) |
| color / background-color | 再描画 | 中 |
| width / height / top / left | レイアウト再計算+再描画 | 重い |
位置を動かすなら left: 20px ではなく transform: translateX(20px)、サイズを変えるなら width ではなく transform: scale() を使います。ほとんどの演出はこの2つで表現できます。
動きに配慮が必要な人がいる
OSには「視差効果を減らす」という設定があり、動きによって不快感や体調不良を感じる人のために用意されています。CSSからはメディアクエリで検出できます。
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}
この数行を入れておくだけで、設定している利用者には動きが出なくなります。アニメーションを使うサイトでは、入れておきたい配慮です。
スクロールに合わせて動かす
「画面に入ったらフェードインさせる」実装は、CSSだけでは完結しません。JavaScriptの Intersection Observer で要素の出現を検知し、クラスを付ける方法が一般的です。
const io = new IntersectionObserver((entries) => {
entries.forEach((e) => {
if (e.isIntersecting) e.target.classList.add("is-visible");
});
}, { threshold: 0.2 });
document.querySelectorAll(".fade-target").forEach((el) => io.observe(el));
スクロールイベントを直接監視する方法より軽く、実装も短く済みます。
よくある失敗
- アニメーション後に元へ戻ってしまう:
animation-fill-mode: forwards(またはショートハンドのboth)を付ける - ページ読み込み直後に一瞬だけ見える:初期状態を
opacity: 0にしておく - 時間が長すぎる:UIの演出は0.2〜0.6秒が自然に感じられる範囲
- 複数要素が同時に出て慌ただしい:
animation-delayを要素ごとに少しずつずらす
