CSS animation-fill-mode Property
Determines how a CSS animation applies styles to its target before and after it executes.
| none | The element returns to its original state before the animation started and after it finishes. |
| forwards | The element retains the style values of the last keyframe after the animation ends. |
| backwards | The element applies the style values of the first keyframe as soon as the animation is applied, during the delay period. |
| both | The element follows the rules for both forwards and backwards, extending styles in both directions. |
Code Examples
A basic example showing an element that stays at its final position and keeps its final color after the animation completes.
<style>
.box {
width: 100px;
height: 100px;
background: #ff0000;
animation-name: slide;
animation-duration: 2s;
animation-fill-mode: forwards;
}
@keyframes slide {
from { transform: translateX(0); }
to { transform: translateX(200px); background: #0000ff; }
}
</style>
<div class="box"></div>An advanced example using both to keep a card hidden during a delay and visible after sliding in, triggered via JavaScript.
<style>
.card {
width: 200px;
padding: 20px;
background: #eeeeee;
opacity: 0;
}
.reveal {
animation: slideIn 1s ease-out 0.5s both;
}
@keyframes slideIn {
0% { opacity: 0; transform: translateY(30px); }
100% { opacity: 1; transform: translateY(0); }
}
</style>
<div id="content-card" class="card">Dynamic Content</div>
<button onclick="activate()">Reveal Card</button>
<script>
function activate() {
const el = document.getElementById("content-card");
el.classList.add("reveal");
el.style.border = "1px solid #333333";
}
</script>Pro Tip
When creating staggered entrance animations for a list of items, use "animation-fill-mode: both" with an "opacity: 0" starting keyframe. This keeps the items hidden during their individual delay periods, ensuring a clean, flicker-free sequence as they appear one by one.
Deep Dive
Think of an animation like a stage play. Usually, when the play is over, the actor goes back to the dressing room and puts on their street clothes. That is the "none" behavior. If you use "forwards", the actor stays on stage in their final pose even after the curtain drops. If you use "backwards", the actor puts on their costume the moment they arrive at the theater, even before the show starts during the "animation-delay". Using "both" ensures the actor is in costume early and stays in their final pose late. This property is the bridge between your static CSS and the temporary world of keyframes.
Best Practices
Use "forwards" when you want an element to remain in its end state, such as a fader that keeps an element invisible. Use "both" if your animation has a delay and the first keyframe is different from the base CSS; this prevents the element from "jumping" visually when the animation finally kicks in after the delay.
Common Pitfalls
A common mistake is expecting "backwards" to do something when there is no "animation-delay" set; without a delay, there is no pre-animation period to observe. Also, remember that "forwards" will not appear to work if the "animation-iteration-count" is set to "infinite", because the animation never actually reaches an end state.
Accessibility
If you use this property to permanently hide an element at the end of an animation (e.g., opacity 0), ensure that the element is also removed from the accessibility tree or disabled if it contains interactive parts, so screen readers do not focus on invisible content.
Dev Data Table: animation-fill-mode property
| default | none |
| animatable | no |
| inherited | no |
| experimental | no |
| year_intro | 2009 |
| year_standard | 2013 |
| js_syntax_1 | object.style.animationFillMode = "forwards"; |
| js_syntax_2 | object.style.setProperty("animation-fill-mode", "forwards"); |
| js_note | When manipulating this property in JavaScript, ensure you use camelCase for the style object property or the exact string for the setProperty method. |
| browsers | { "Chrome": 43, "Edge": 12, "Firefox": 16, "Safari": 9, "Opera": 30, "Chrome Android": 43, "Safari on iOS": 9, "Samsung Internet": 4, "Opera Mobile": 30 } |