animation-fill-mode

animation-fill-mode controls whether keyframe styles apply outside the animation’s active interval. It does not permanently rewrite the ordinary CSS declaration or document state.

Compare no fill with forwards

Both squares travel for one second. None returns to the base position afterward; forwards keeps the last encountered keyframe while the animation remains applied.

animation-fill-mode comparisonLink

HTML and CSS

HTML

<input class="run" id="run" type="checkbox" /><label for="run"
  >Run the demonstration; uncheck to reset</label
>
<div class="stage">
  <p>None</p>
  <div class="box" aria-hidden="true"></div>
  <p>Forwards</p>
  <div class="box keep" aria-hidden="true"></div>
</div>

CSS

@keyframes travel {
  from {
    transform: translateX(0);
  }
  to {
    transform: translateX(100px);
  }
}
.stage {
  background: #eff6ff;
  padding: 1rem;
}
.box {
  width: 50px;
  height: 35px;
  background: #2563eb;
  margin-block: 0.5rem;
}
label {
  display: inline-block;
  padding: 0.75rem;
}
.run:checked ~ .stage .box {
  animation: travel 1s linear;
}
.run:checked ~ .stage .keep {
  animation-fill-mode: forwards;
}
@media (prefers-reduced-motion: reduce) {
  .run:checked ~ .stage .box {
    animation-name: none;
  }
}

Edit HTML or CSS to update the preview as you type. Copy code snippet copies the selected tab. Preview spacing and font defaults are not included.

Apply the starting state during a delay

The square is ordinarily blue. Backwards supplies the amber first keyframe immediately during the one-second delay. After playback ends it returns to blue, since backwards does not retain the end.

animation-fill-mode practical exampleLink

HTML and CSS

HTML

<input class="run" id="run" type="checkbox" /><label for="run"
  >Run the demonstration; uncheck to reset</label
>
<div class="stage"><div class="box" aria-hidden="true"></div></div>

CSS

@keyframes travel {
  from {
    transform: translateX(0);
  }
  to {
    transform: translateX(100px);
  }
}
.stage {
  background: #eff6ff;
  padding: 1rem;
}
.box {
  width: 50px;
  height: 35px;
  background: #2563eb;
  margin-block: 0.5rem;
}
label {
  display: inline-block;
  padding: 0.75rem;
}
@keyframes tint {
  from {
    background: #fbbf24;
  }
  to {
    background: #0f766e;
  }
}
.run:checked ~ .stage .box {
  animation: tint 1s linear 1s backwards;
}
@media (prefers-reduced-motion: reduce) {
  .run:checked ~ .stage .box {
    animation-name: none;
  }
}

Edit HTML or CSS to update the preview as you type. Copy code snippet copies the selected tab. Preview spacing and font defaults are not included.

Values and defaults

The initial value is none and the property is not inherited. Forwards retains the last keyframe encountered. Backwards supplies the first relevant keyframe during delay. Both combines those behaviors. First/last depend on animation-direction and iteration count; forwards does not always mean the 100% keyframe.

Common mistakes

Removing the animation removes its fill effect. With transform/opacity animation, retained fill can also retain stacking-context behavior. A fade-in should not make essential content unavailable when CSS or motion is disabled; keep a useful ordinary state. Fill is visual styling, not accessible message announcement or focus management. A later shorthand resets it, and comma-separated values map to animation-name order.

Learn animation-direction, animation-delay, and animation.

The demonstrations are stationary when prefers-reduced-motion:reduce is active. Their code remains available for inspection.

Sources and browser support

MDN: animation-fill-mode describes the syntax and links to the specification and compatibility data. Check individual values in that table when supporting older browsers.