Some Ideas about animation-fill-mode: animation-fill-mode
Animation-fill-mode is an attribute of css3 animation. It can control the style of elements before and after the animation is executed. An animation with a delay and executed in the normal direction (from 0% to 100% in the normal direction). The execution process can be described as follows:
# Demo1 {. target. animate {animation-name: move_1; animation-duration: 2 s; animation-delay: 1 s; &.tar get_1 {animation-fill-mode: backwards ;} &.tar get_2 {animation-fill-mode: forwards;} &.tar get_3 {animation-fill-mode: both ;}}@ keyframes move_1 {0% {transform: translate (-50px, 0);} 50% {transform: translate (0, 0);} 100% {transform: translate (50px, 0 );}}
In the preceding demo, A move_1 animation is defined, which contains three key frames. The first frame offsets the element 50px to the left, and the last frame offsets the element 50px to the right, this offset is relative to the initial state of the element (that is, the State where no animation is added ). In the demo, there are three elements from top to bottom, which apply the three values of the animation-fill-mode attribute: backwards, forwards, and both. Combining the preceding descriptions of these three attribute values, we believe it is difficult to understand the animation effects of the three elements in the demo:
Backwards and both make the first and third elements immediately change to the first frame of the animation after the animation is added. The second element does not apply the status of the first frame.
Forwards and both make the second and third elements remain in the last frame of the animation after the animation ends. There are no 1st elements.
The above content may make people think that animation-fill-mode is a simple attribute, because it is very simple and clear. Even so, when I recently made some animation effects, I found that it is not so easy to use this attribute completely and comprehensively when it is actually used, especially when we need to apply multiple animations at the same time to define continuous and complex animations, we may encounter some points that we cannot understand by theory during the animation writing process, although in the end, we can always find a way to solve the problem we encountered. It is because this attribute has only a few values after all. More debugging can solve the problem, but it is done, I still want to solve the problem of why I wrote it before. Therefore, this article studies the misunderstanding of animation-fill-mode from some unconventional perspectives,I cannot guarantee that some of the methods I have put forward in this article are correct. I can only draw such conclusions based on my current experience. I hope this article will introduce some ideas that are more reliable and perfect.
First, I want to explain the theoretical knowledge of animation-fill-mode again:
1) in the basic knowledge of animation-fill-mode, there are several keywords: animation wait time (also called animation Delay Time). After the animation ends, the first frame and the last frame. The deeper meanings of these keywords are:
A. backwards must be effective within the animation delay period;
B. forwards takes effect only after the animation is completed. For a loop animation, it does not take effect after the animation is completed;
C. The first frame and the last frame are not absolute, that is, the first frame does not always correspond to the 0% frame, and the last frame does not always match the 100% frame. Whether 0% is the first frame or 100% is the first frame is related to the other two animation attributes: animation-direction and animation-iteration-count. For example, when animation-direction is alternate and animation-iteration-count is 2, the first and last frames are both 0%. As for why, you can simply draw a picture to understand:
# Demo2 {. target. animate {animation-name: move_2; animation-duration: 2 s; animation-delay: 1 s; &.tar get_1 {animation-fill-mode: backwards ;} &.tar get_2 {animation-fill-mode: forwards;} &.tar get_3 {animation-fill-mode: both ;}}@ keyframes move_2 {50% {transform: scale (1.2, 1.2 );}}
In this demo, you will see that the three elements apply different animation-fill-mode, but the final effect is the same. This is because 0%, 100%, and are not defined in the animation, so that the first and last frames required by the animation-fill-mode cannot be found. Although in the demo animation above, 50% is the only frame in the animation definition. According to our understanding of uniqueness, 50% can be regarded as a frame, it can also be viewed as the last frame,Animation-fill-mode only recognizes 0% and 100% in the animation definition, rather than the first and last frames in the animation definition..
Does it mean that if there is no 0% or 100%, the animation-fill-mode will certainly be ineffective?
Actually not.When there is no 0% or 100% in the animation definition, it does not mean that the animation has no start frame and end frame. Any animation must have the start frame and end frame, by default, the style corresponding to the start frame and the end frame is the style before the animation that is not added to the element. We can use 0% or 100%, to overwrite the definition of the default start and end frames.That is to say, when there is no 0% or 100%, the animation-fill-mode still works, but it uses the initial state of the element, so you cannot see it.
In the conclusion of the previous paragraph, I did not see an introduction on w3c, But I guessed it based on my own thoughts and observations. Next, I will use chrome's animation debugging tool to help explain my judgment. Later I will introduce the practice of animation-fill-mode in multiple animations, I will also use these theories to explain them in combination with an example.
The new version of chrome provides the animation debugging function, which can be opened as follows:
# Demo3 {. target. animate {animation-name: move_3; animation-duration: 2 s; animation-delay: 1 s; &.tar get_1 {animation-fill-mode: none ;} &.tar get_2 {animation-fill-mode: backwards;} &.tar get_3 {animation-fill-mode: forwards;} &.tar get_4 {animation-fill-mode: both ;}}} @ keyframes move_3 {50% {transform: scale (1.2, 1.2 );}}
However, the purpose of this section is not to illustrate the animation effect of this demo, but to introduce how to view the scope of the animation process from the animation console:
# Demo4 {. target {transform: scale (1.2, 1.2 );}. target. animate {animation-duration: 2 s; animation-delay: 1 s; &.tar get_1 {animation-fill-mode: none; animation-name: move_4_01 ;} &.tar get_2 {animation-fill-mode: backwards; animation-name: move_4_01;} &.tar get_3 {animation-fill-mode: forwards; animation-name: move_4_01 ;} &.tar get_000002 {animation-fill-mode: none; animation-name: move_4_02;} &.tar get_2_02 {animation-fill-mode: backwards; animation-name: move_4_02 ;} &.tar get_3_02 {animation-fill-mode: forwards; animation-name: move_4_02 ;}}@ keyframes move_4_01 {0% {transform: translate (-50px, 0 );} 50% {transform: translate (0, 0);} 100% {transform: translate (50px, 0) ;}@ keyframes move_4_02 {0% {transform: translate (-50px, 0) scale (1.2, 1.2);} 50% {transform: translate (0, 0) scale (1.2, 1.2);} 100% {transform: translate (50px, 0) scale (1.2, 1.2 );}}
In the above section, I used arrows to map the elements to the animation element timeline in the animation console for ease of understanding.
In this demo, each element has a transform: scale (1.2, 1.2) setting by default, and then two animations are defined. The move_4_01 animation style definition also contains a transform attribute, the default transform settings of the element are not retained. The style definition of move_4_02 also contains a transform setting. Unlike move_4_01, the animation retains the default scale (1.2, 1.2) Setting of the element.
Six elements are used in the demo. They are divided into three groups based on animation-fill-mode to correspond to different animation processes. The two elements in each group are, apply the move_4_01 and move_4_02 animations respectively.
Through the animation wait phase on the timeline, the animation execution phase, and the animation end phase, you can take three time points to observe the performance of the elements, which can help analysis in the animation process, the rule that exists when the animation attribute conflicts with the initial attribute:
Animation wait stage:
# Demo5 {. target. animate {animation-duration: 1 s, 1 s; animation-delay: 1 s, 2 s; animation-fill-mode: both; &.tar get_1 {animation-name: move_5, bg_change_5;} &.tar get_2 {animation-name: bg_change_5, move_5 ;}}@ keyframes move_5 {0% {transform: translate (-50px, 0);} 50% {transform: translate (0, 0);} 100% {transform: translate (50px, 0) ;}@ keyframes bg_change_5 {0% {background-color: orange; transform: scale (0.8) ;}100% {background-color: red; transform: scale (1.2 );}}
In this demo, two animations are defined. move_5 changes the offset of the element on the X axis, while bg_change_5 changes the zoom and background color of the element at the same time. Both elements apply the two animations at the same time. Except for the order of application time, other parameters, such as latency, duration, and animation-fill-mode, are identical. In combination with the timeline displayed on the animation console, let's take a look at the regularity of these two elements in the animation process.
Take the animation wait stage as an example:
# Demo6 {. target: not(.tar get_1) {visibility: hidden; opacity: 0 ;}. target. animate {&.tar get_2 {animation-name: move_6_01, move_6_02; animation-duration: 1 s, 1 s; animation-delay: 0 s, 2 s; animation-fill-mode: both ;}}@ keyframes move_6_01 {0% {visibility: hidden; opacity: 0; transform: translate (-50px, 0);} 100% {visibility: visible; opacity: 1; transform: translate (0, 0) ;}@ keyframes move_6_02 {100% {visibility: hidden; opacity: 0; transform: translate (50px, 0 );}}
As you can see, I have defined two animations, move_6_01 and move_6_02. These two animations are applied to the element .tar get_2 following the order of 01 02. The animation duration is 1 s, the delay time of the first animation is 0, and the delay time of the second animation is 2 s, so that the fade-in and fade-out time is 1 s, and the stay time in the middle is also 1 s;Animation-fill-mode: both. Then, the initial attribute visibility: hidden, opactity: 0 is set for the element .tar get_2 .. Target_1 is just a comparison element and no animation effect is added.
When I ran this code, I finally found that there was no animation effect at all, and the animation console had already listened to the animation, but the element could not see the animation effect:
# Demo7 {. target: not(.tar get_1) {visibility: hidden; opacity: 0 ;}. target. animate {&.tar get_2 {animation-name: move_6_01, move_6_02; animation-duration: 1 s, 1 s; animation-delay: 0 s, 2 s; animation-fill-mode: both, forwards ;}}}
In this step, the effect of Fade-in and stay-out has come out, but the effect of fade-out has not come out.
Although I finally debugged the animation without understanding the principle, I still think it is necessary to study it in depth, this is my original intention to write this article.With the previous conclusions, let's take a look at how to analyze the causes of the phenomena in the previous two steps.
Let's take a look at the animation timeline of demo6 (the first in this section:
# Demo8 {. target: not(.tar get_1) {visibility: hidden; opacity: 0 ;}. target. animate {&.tar get_2 {animation-name: move_8_01, move_8_02; animation-duration: 1 s, 1 s; animation-delay: 0 s, 2 s; animation-fill-mode: both, forwards ;}}@ keyframes move_8_01 {0% {visibility: hidden; opacity: 0; transform: translate (-50px, 0);} 100% {visibility: visible; opacity: 1; transform: translate (0, 0) ;}@ keyframes move_8_02 {0% {visibility: visible; opacity: 1; transform: translate (0, 0 );} 100% {visibility: hidden; opacity: 0; transform: translate (50px, 0 );}}
Through this example, we hope that you can understand the practical methods of some theories summarized in this article.
Summary
I will not talk about other things. I will refine some of the conclusions mentioned in this article. I hope these things will help you with complicated animations in the future:
1. The animation is independent and each has its own timeline, which does not affect each other.
2. animation-fill-mode only recognizes 0% and 100% in the animation definition, rather than the first and last frames in the animation definition.
3. when there is no 0% or 100% in the animation definition, it does not mean that the animation has no start frame and end frame. Any animation must have the start frame and end frame, by default, the style corresponding to the start frame and the end frame is the style before the animation that is not added to the element. We can use 0% or 100%, to overwrite the definition of the default start and end frames.
4. In the animation console, the solid part of the timeline is the process of animation. When an animation attribute conflicts with an initial attribute, the attribute priority defined in the animation is always higher than the initial attribute of the element as long as an element is in the animation action.
5. in multi-animation effects, you must determine which animation has a high priority at any time point. You only need to find the corresponding line at this time point on the animation console, the intersection of the line and the solid part of all animations (the animation action process) is in the top-down order, and the priority of the down point is higher.
Thank you for reading.