CSS講座 / キーフレームアニメーション:再生・終了状態・一時停止
CSSのキーフレームアニメーションは、時間軸上の値を定義し、ホバーなどの値変更がなくても再生できます。所要時間、遅延、反復回数、終了前後の値、一時停止はそれぞれ別の設定です。
transitionとanimationを使い分ける
transitionはホバーやクラス変更などによる前後の値を補間します。animationはキーフレームに開始・途中・終了の値を書き、適用と遅延の後に再生できます。反復や方向も別に指定できます。
ボタンの色変更だけならtransitionが簡潔です。通知の登場や複数段階の視覚説明ならanimationを検討できます。同じ要素の同じプロパティを両方で制御すると、どの値が効くか追いにくいため、実習では役割を分けます。
キーフレームを要素の再生設定へ結び付ける
fromは0%、toは100%で、途中は50%などで定義します。名前を宣言するだけでは再生せず、要素のanimation-nameから参照します。
@keyframes travel {
0% { transform: translateX(0); }
50% { transform: translateX(3rem); }
100% { transform: translateX(6rem); }
}
.marker { animation: travel 4s linear 1s 1 normal forwards; }
これは完全例の同名ルールを短く表したものです。4sは一回の時間、1sは開始待ちです。durationを省略すると初期値0秒なので過程を観察しにくくなります。最初は個別のプロパティで時間と回数を区別します。
timing-functionは進み方、iteration-countは回数、directionは方向、fill-modeは再生範囲外の値、play-stateは進行の停止を扱います。infiniteは無限反復で、pausedは現在の進行を一時停止します。実習はlinearを使いますが、等間隔のキーフレームでも進み方の関数で位置の変化は異なります。MDNの@keyframesを参照してください。
方向・回数・fill-modeを組み合わせる
normalは最初から最後、reverseは逆、alternateは一回目が順方向で次が逆方向です。整数回を完了する条件で、alternateを二回なら最後は開始側へ到達します。
forwardsが保つのは常に100%の値ではなく、方向と回数によって最後に到達したキーフレームです。例ではnormal一回は6rem、reverse一回とalternate二回は0の位置を保ちます。端数の回数は途中で終わることもあるので区別します。MDNのanimation-fill-modeを参照してください。
noneは遅延中も終了後も基本CSSです。forwardsは終了後、backwardsは遅延中、bothは両方にキーフレームの値を使います。例では基本位置を1rem、開始0、終了6remに分け、違いが見えるようにしています。必要な案内本文は、アニメーションなしでも完成状態で読める基本CSSにします。
完全例で一設定ずつ変える
次をanimation-lab.htmlとして保存します。上の案内が短く現れ、下の装飾は一秒後に四秒かけて動きます。変更を保存したら再読み込みし、開始から比べます。
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Keyframes and end states exercise</title>
<style>
*, *::before, *::after { box-sizing: border-box; }
body { margin: 0; padding: 1rem; color: #183044; font-family: sans-serif; line-height: 1.6; }
main { max-width: 46rem; margin-inline: auto; }
h1 { font-size: 1.5rem; } h2 { font-size: 1.2rem; }
button, input { font: inherit; }
button { cursor: pointer; }
:focus-visible { outline: 3px solid #164f73; outline-offset: 3px; }
.notice { padding: 1rem; border: 1px solid #90bdd8; border-radius: .5rem; background: #eaf4fa;
opacity: 1; transform: none; animation: appear 400ms ease-out; }
@keyframes appear {
from { opacity: 0; transform: translateY(.5rem); }
to { opacity: 1; transform: translateY(0); }
}
.track { margin-block: 1rem; padding: 1rem; border: 2px dashed #8a9ba7; }
.marker { width: 2rem; height: 2rem; border-radius: .25rem; background: #166b92;
transform: translateX(1rem);
animation-name: travel; animation-duration: 4s; animation-timing-function: linear;
animation-delay: 1s; animation-iteration-count: 1; animation-direction: normal;
animation-fill-mode: forwards; }
@keyframes travel {
0% { transform: translateX(0); background-color: #166b92; }
50% { transform: translateX(3rem); background-color: #6a3989; }
100% { transform: translateX(6rem); background-color: #28633b; }
}
#pause:checked ~ .track .marker { animation-play-state: paused; }
@media (prefers-reduced-motion: reduce) {
.notice, .marker { animation: none; }
}
</style>
</head>
<body>
<main>
<h1>Check entrance and movement</h1>
<p class="notice">This notice remains readable without animation.</p>
<h2>Comparing end states</h2>
<p>Movement starts one second after loading. Refresh the page to compare again.</p>
<input id="pause" type="checkbox"><label for="pause">Pause movement</label>
<div class="track"><div class="marker" aria-hidden="true"></div></div>
<p>The colors and movement are decorative. Essential information remains available independently of the animation, as in this sentence.</p>
</main>
</body>
</html>
- 標準では遅延中1rem、開始時0、終了後6remです。待ち時間と開始値が違うことを確認します。
- fill-modeだけをnoneへ変え、終了後に基本の1remと青へ戻ることを見てforwardsへ戻します。
- bothへ変えると遅延中も開始値0になります。確認してforwardsへ戻します。
- 回数1のままreverseへ変え、終了0を確認してnormalへ戻します。
- alternateの一回と二回を比べます。最後は回数1とnormalへ復元します。
- 再読み込み直後にPauseをチェックし、待ってから解除します。最初からやり直すのでなく、止めた進行から再開するか確認します。
動きがなくても内容を読めるようにする
動きを減らす条件では案内と装飾のanimationを外します。基本のopacityが1なので案内は読め、装飾は基本位置1remに残ります。読める値を最後のキーフレームやforwardsだけへ置くと、アニメーションがないときに内容が消える場合があります。
OSまたは開発者ツールで条件を有効にして再読み込みし、静止しても内容が見えるかを確認して設定を戻します。MDNのprefers-reduced-motion、画面と操作の点検を参照してください。
無限反復を付ける前に目的と停止方法を決めます。動かないなら名前、時間、動きを減らす条件を確認し、終了位置が違うなら方向、回数、fill-mode、基本CSSを分けて調べます。




