8.

CSS animation-fill-mode|none・forwards・backwards・bothの違い

編集
この記事の要点
  • animation-fill-mode は CSS アニメーション実行前・実行後の状態をどう扱うかを指定するプロパティ
  • 値は none(既定)・forwards(終了後のスタイルを保持)・backwards(開始前から開始キーフレームのスタイルを適用)・both(両方)
  • forwards を付けないとアニメ終了後に元の見た目に戻る。これが意図せず起こりやすい
  • animation-delay と組み合わせて遅延中の見た目を制御するには backwards が必要
  • ショートハンド animation: name dur fill-mode ... の中に書くか、個別プロパティで指定する

animation-fill-mode プロパティとは

animation-fill-mode は、CSS アニメーションが実行されていない時間帯(再生前のディレイ中、または再生終了後)に、要素にキーフレームのスタイルを適用するかどうかを指定するプロパティです。指定しないと、アニメーションが終わった瞬間に元の CSS スタイルにパッと戻ってしまうため、「動いた後の見た目をそのまま残したい」ときには必ず使うことになります。

構文

.box {
  animation-name: slide;
  animation-duration: 1s;
  animation-fill-mode: forwards;
}

/* ショートハンド: 一行で書く場合 */
.box {
  animation: slide 1s ease-in-out 0.5s 1 normal forwards;
  /*         name  dur  timing   delay count direction fill-mode */
}

値の意味

意味
none(既定)アニメーション再生前後で、要素の見た目は元の CSS のまま。終了後は from の状態を保持しない
forwardsアニメーション終了後、最後のキーフレーム(to / 100%)の状態を保持する
backwardsアニメーション開始前(特に animation-delay 中)から、最初のキーフレーム(from / 0%)の状態を適用する
bothforwardsbackwards の両方を有効にする

使い分けを目で見て理解する

none(既定)

「ふわっと動かして元の場所に瞬時に戻る」状態です。ローディングインジケータのようにループ前提なら問題ありませんが、1 回再生で終了状態のまま固定したい場合は意図せぬ挙動になります。

@keyframes slide {
  from { transform: translateX(0);     opacity: 0; }
  to   { transform: translateX(200px); opacity: 1; }
}

.box-none {
  animation: slide 1s ease-out;
  /* fill-mode 指定なし → 終了後に瞬時に左に戻り opacity も 0 に戻る */
}

forwards: 終了状態を保持する(最頻出)

1 回再生のフェードインや、スライドインの定番設定です。これがないと UI が点滅するので、ほぼ必須と考えてよい値です。

@keyframes fade-in {
  from { opacity: 0; transform: translateY(20px); }
  to   { opacity: 1; transform: translateY(0); }
}

.card {
  opacity: 0;                          /* 初期は非表示 */
  animation: fade-in 0.6s ease-out forwards;
  /* 終了後も opacity:1 / translateY(0) のまま固定 */
}

backwards: ディレイ中から開始キーフレームを適用する

animation-delay がある場合、none / forwards だと「ディレイ中は元の見た目」「ディレイ後にいきなり開始キーフレームへ」とカクっとした切替が起こります。backwards を指定すると、ディレイ中から from の状態が適用されるので自然なフェードイン演出になります。

.delayed {
  animation: fade-in 0.6s ease-out 0.5s backwards;
  /* 0.5 秒のディレイ中も opacity:0, translateY(20px) を維持 */
}

both: 順次表示する UI で重宝

リスト要素を時間差で表示する場合、both + animation-delay をセットで使うと、開始前は非表示 → 順番にフェードイン → 終了状態固定、というよくある演出が綺麗に決まります。

.list > li {
  animation: fade-in 0.5s ease-out both;
}
.list > li:nth-child(1) { animation-delay: 0.0s; }
.list > li:nth-child(2) { animation-delay: 0.1s; }
.list > li:nth-child(3) { animation-delay: 0.2s; }
.list > li:nth-child(4) { animation-delay: 0.3s; }

よくあるハマりポイント

  • 「動いた後に元に戻ってしまう」forwards または both を指定する
  • ディレイ中に要素がチラッと見えてしまうbackwards または both を指定する
  • ループアニメ(無限再生)では fill-mode は実質意味を持たない。最後の状態に戻る前に次のサイクルが始まるため
  • fill-mode はカスケードに影響しない。あくまで「アニメーション中のスタイル扱い」なので、JS で要素のクラスを変えれば普通に上書きできる

関連プロパティ

プロパティ役割
animation-name使用する @keyframes 名
animation-duration1 サイクルの長さ
animation-delay開始までの遅延時間
animation-iteration-count繰り返し回数(infinite で無限)
animation-direction再生方向(normal / reverse / alternate)
animation-timing-functionイージング

ブラウザサポート

animation-fill-mode は IE10 以降を含むほぼすべてのモダンブラウザでサポートされており、ベンダープレフィックスを書く必要はもうありません。Safari の古いバージョンでだけ -webkit- 付きの記述が必要だった時期がありましたが、現在は不要です。

JavaScript からの動的制御

クラス付け替えでアニメ発火させるのが定石ですが、終了タイミングを掴みたい場合は animationend イベントが使えます。fill-mode: forwards の状態をクリアして再生し直す例:

const el = document.querySelector('.card');

el.addEventListener('animationend', (e) => {
  console.log('animation finished:', e.animationName);
  // 必要なら fill-mode の影響を切るためインラインスタイルを当て直す
});

// 再生をリセットして再度走らせる
el.style.animation = 'none';
void el.offsetWidth;          // リフローを強制
el.style.animation = '';      // CSS で指定したアニメに戻す

関連記事

編集
Post Share
子ページ

子ページはありません

同階層のページ
  1. animation-nameプロパティ
  2. animation-duration プロパティ
  3. animation-timing-functionプロパティ
  4. animation-delayプロパティ
  5. animation-iteration-countプロパティ
  6. animation-directionプロパティ
  7. animation-play-stateプロパティ
  8. animation-fill-modeプロパティ
  9. animationプロパティ

最近更新/作成されたページ