Maintaining the final state at end of a CSS3 animation
CssCss AnimationsCss Problem Overview
I'm running an animation on some elements that are set to opacity: 0;
in the CSS. The animation class is applied onClick, and, using keyframes, it changes the opacity from 0
to 1
(among other things).
Unfortunately, when the animation is over, the elements go back to opacity: 0
(in both Firefox and Chrome). My natural thinking would be that animated elements maintain the final state, overriding their original properties. Is this not true? And if not, how can I get the element to do so?
The code (prefixed versions not included):
@keyframes bubble {
0% { transform:scale(0.5); opacity:0.0; }
50% { transform:scale(1.2); opacity:0.5; }
100% { transform:scale(1.0); opacity:1.0; }
}
Css Solutions
Solution 1 - Css
Try adding animation-fill-mode: forwards;
. For example like this:
-webkit-animation: bubble 1.0s forwards; /* for less modern browsers */
animation: bubble 1.0s forwards;
Solution 2 - Css
If you are using more animation attributes the shorthand is:
animation: bubble 2s linear 0.5s 1 normal forwards;
This gives:
bubble
animation name2s
durationlinear
timing-function0.5s
delay1
iteration-count (can be 'infinite
')normal
directionforwards
fill-mode (set 'backwards' if you want to have compatibility to use the end position as the final state[this is to support browsers that has animations turned off]{and to answer only the title, and not your specific case})
Solution 3 - Css
IF NOT USING THE SHORT HAND VERSION: Make sure the animation-fill-mode: forwards
is AFTER the animation declaration or it will not work...
animation-fill-mode: forwards;
animation-name: appear;
animation-duration: 1s;
animation-delay: 1s;
vs
animation-name: appear;
animation-duration: 1s;
animation-fill-mode: forwards;
animation-delay: 1s;
Solution 4 - Css
Use animation-fill-mode: forwards;
animation-fill-mode: forwards;
The element will retain the style values that is set by the last keyframe (depends on animation-direction and animation-iteration-count).
Note: The @keyframes rule is not supported in Internet Explorer 9 and earlier versions.
Working example
div {
width: 100px;
height: 100px;
background: red;
position :relative;
-webkit-animation: mymove 3ss forwards; /* Safari 4.0 - 8.0 */
animation: bubble 3s forwards;
/* animation-name: bubble;
animation-duration: 3s;
animation-fill-mode: forwards; */
}
/* Safari */
@-webkit-keyframes bubble {
0% { transform:scale(0.5); opacity:0.0; left:0}
50% { transform:scale(1.2); opacity:0.5; left:100px}
100% { transform:scale(1.0); opacity:1.0; left:200px}
}
/* Standard syntax */
@keyframes bubble {
0% { transform:scale(0.5); opacity:0.0; left:0}
50% { transform:scale(1.2); opacity:0.5; left:100px}
100% { transform:scale(1.0); opacity:1.0; left:200px}
}
<h1>The keyframes </h1>
<div></div>
Solution 5 - Css
I had an issue using forwards
: at least in Chrome, even after the animation ended, the renderer was still sucking up graphics resources, making the application less responsive.
An approach that does not cause this trouble is by using an EventListener
.
CSS animations emit events, so you can use the animationend event to intervene when the animation ends.
CSS
.fade_in {
animation: fadeIn 2s;
}
@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
JavaScript
const element = document.getElementById("element-to-be-animated");
element.addEventListener("animationend", () => {
// Set your final state here. For example:
element.style["opacity"] = 1;
}, { once: true });
The option once: true
tells the engine to remove the event listener after its execution, leaving your application fresh and clean.
I have created a JSFiddle to show how it works.