transition を 1 つの例で
transition はブラウザに「このプロパティが変わったら、すぐに切り替えずにこれだけの時間をかけてアニメーションさせて」と伝えます。:hover だけでなく、要素の通常のルールに書きます:
1 つ目のボタンにホバーすると、0.4 秒かけて色が緑に変わり、4px 浮き上がります。ポインターを離すと、同じ transition が逆向きに再生されます。2 つ目のボタンは transition: none なので、すぐに切り替わります。キーボードで操作する人には :focus-visible で同じ効果が届きます。
transition のショートハンド
transition: background-color 0.3s ease-in-out 0.1s;
/* property duration timing delay */
| 個別のプロパティ | 指定するもの | 初期値 |
|---|---|---|
transition-property | アニメーションさせるプロパティ (all かリスト) | all |
transition-duration | かける時間 (s か ms) | 0s |
transition-timing-function | 速さの曲線 | ease |
transition-delay | 始まるまでの待ち時間 (負の値も可) | 0s |
duration の初期値は 0s なので、指定するまで何もアニメーションしません。ショートハンドでは、1 つ目の時間が常に duration、2 つ目が delay です。プロパティごとに設定を変えるなら、カンマで区切ります:
.card {
transition: transform 0.2s ease-out, box-shadow 0.4s ease-out;
}
タイミング関数の比較
タイミング関数は、transition の間に速さがどう変わるかを決めます。Play を押すと、7 本のバーがすべて同じ 1.5 秒で同じ距離を動きます:
| タイミング関数 | 印象 |
|---|---|
linear | 一定の速さ。機械的 |
ease (初期値) | すばやく始まり、ゆっくり止まる |
ease-in | ゆっくり始まり、速く終わる。去っていくものに向く |
ease-out | 速く始まり、ゆっくり終わる。入ってくるものに向く |
ease-in-out | 両端がゆっくり |
cubic-bezier(x1, y1, x2, y2) | 自分で決めた曲線。y が 1 を超えると行き過ぎてから戻る |
steps(n) | 途中のフレームなしで、n 回の等しい段階で飛ぶ |
ホバーの効果やメニューには、150ms から 300ms の ease-out が反応よく感じられます。
transition できるもの
途中の値があるプロパティは transition できます。色、長さ (width、padding、margin)、opacity、transform、box-shadow、border-radius、filter、background-color などです。display や font-family のようにキーワードの間で切り替わるプロパティは、すぐに切り替わります。
一番よくつまずくのが height: auto です。height: 0 から height: auto に開くパネルは、初期状態ではアニメーションしません。ブラウザは 0 と「auto」の間の値を計算しないからです。確実な回避策は、1 行だけの grid のラッパーで行を 0fr から 1fr にすることです:
aria-expanded はスクリーンリーダーの利用者に、パネルが開いているかどうかを伝えます。アニメーションだけでは伝わりません。
transition の終了時にコードを実行する
transitionend イベントは、transition が終わったときにプロパティごとに 1 回発生します。フォーカスを移す、要素を取り除くなど、動きの後に何かをするときに使います:
動きを減らす設定を尊重する
画面上の動きでめまいがしたり気が散ったりするため、システムの設定で「視差効果を減らす」をオンにしている人がいます。メディアクエリを使って、色や opacity のフェードは残し、大きな動きはやめましょう:
@media (prefers-reduced-motion: reduce) {
.btn { transition: background-color 0.2s ease; } /* no movement, only the color */
}
transition をなめらかに保つ
transform と opacity は一番負荷の軽いアニメーションのプロパティです。ブラウザはレイアウトを計算し直さずに、要素を動かしたりフェードさせたりできます。width、height、top、margin を transition させると、ブラウザは毎フレームページを配置し直すので、遅いスマートフォンではカクつくことがあります。何かを動かすなら、left や margin より transform: translate() を使いましょう。関数は transform のページ で解説しています。
よくある間違い
transitionを:hoverのルールにだけ書く。 アニメーションで入りますが、ホバーが終わるとすぐに戻ります。transitionは基本のルールに書きましょう。- 時間に単位がない。
transition: opacity 300は無効です。300msか0.3sと書きます。 transition: all。 変わるプロパティをすべてアニメーションさせるので、意図しないものまで動き、レイアウトの変化が重くなることがあります。プロパティを列挙しましょう。display: noneでフェードすると思う。displayはすぐに切り替わります。代わりにopacityをフェードさせましょう (フェードが終わったらvisibility: hiddenにします)。height: autoへ transition させる。 飛んでしまいます。上のgrid-template-rowsのテクニックを使いましょう。- 小さな操作に長い時間をかける。 ボタンやメニューで約 400ms を超えると遅く感じます。
よくある質問
CSS の transition はどう動きますか?
要素に、どのプロパティをどれくらいの時間でアニメーションさせるかを宣言します。例: transition: background-color 0.3s ease;。そのプロパティの値が (:hover、クラス、JavaScript で) 変わると、ブラウザはすぐに切り替えずに古い値から新しい値へアニメーションさせます。
transition のショートハンドの値の順番は?
transition: property duration timing-function delay; です。例: transition: opacity 0.3s ease-in 0.1s;。厳密なルールは、1 つ目の時間が duration、2 つ目が delay ということだけです。複数の transition はカンマで区切ります。
CSS の transition が効かないのはなぜですか?
よくある原因は、transition が :hover のルールにしかない (アニメーションで入ってすぐ戻る)、アニメーションできないプロパティ (display、auto への height)、時間に単位がない (0.3s ではなく 0.3)、要素がページに追加されたのと同じ瞬間に値が変わる、のいずれかです。
height: auto に transition できますか?
すべてのブラウザで普通の height の transition ではできません。auto への補間には新しい interpolate-size プロパティが必要で、まだどこでも使えるわけではありません。よくある回避策は、grid のラッパーで grid-template-rows を 0fr から 1fr にアニメーションさせるか、max-height を内容より大きい値までアニメーションさせることです。
CSS の transition と animation の違いは何ですか?
transition は、プロパティが変わったときに 2 つの値の間で 1 回だけ動きます。animation は @keyframes を使い、たくさんの段階を持てて、ページの読み込み時に自分で始まり、繰り返しやループもできます。