In this article, we will take a more comprehensive and detailed look at all aspects of CSS animation, explaining the usage of each attribute and illustrating advanced usage, in the hope that it will be a good tutorial from introductory to advanced.

 CSS Animation Introduction and Syntax

 First, let’s briefly introduce CSS animations.


The latest version of CSS animations is defined by the specification, CSS Animations Level 1.


CSS animations are used to transition elements from one CSS style configuration to another.


An animation consists of two parts: the style rules that describe the animation and the keyframes that specify the animation start, end, and midpoint styles.

 In short, look at the example below:

div {
    animation: change 3s;
}

@keyframes change {
    0% {
        color: #f00;
    }
    100% {
        color: #000;
    }
}

  1. animation: move 1s section is the first part of the animation, which is used to describe the individual rules of the animation; the

  2. @keyframes move {} section is the second part of the animation, which is used to specify the keyframes for the start and end of the animation, as well as the style of the midpoint.

 A CSS animation must consist of both of these parts.

 CSS Animation Syntax

 Next, let’s take a brief look at the syntax of CSS animations.


To create an animation sequence, you need to use the animation attribute or its subattribute, which allows you to configure the timing, duration, and other details of the animation, but it does not allow you to configure the actual behavior of the animation, which is implemented by the @keyframes rule.

 The sub-properties of animation are:


  • animation-name: Specifies the name of the keyframe described by @keyframes.

  • animation-duration: set the duration of one cycle of the animation.

  • animation-delay: set the delay time, i.e. the time between when the element is loaded and when the animation sequence starts executing.

  • animation-direction: set whether the animation will run in reverse or back to the start position after each run.

  • animation-iteration-count: set the animation iteration count, you can specify infinite.

  • animation-play-state: allow to pause and resume the animation.

  • animation-timing-function: set the speed of the animation, i.e. set how the animation changes between keyframes by creating an acceleration curve.

  • animation-fill-mode: specify how to apply styles to the target element before and after the animation is executed.

  • The @keyframes rule, of course, should be included for an animation to run, to set the animation keyframes internally

 Which, for an animation:


  • Mandatory: animation-name , animation-duration and @keyframes rules

  • Non-required items: animation-delay , animation-direction , animation-iteration-count , animation-play-state , animation-timing-function , animation-fill-mode , not that they are unimportant of course, just that they all have default values when not set


A simple DEMO has been given above, use the above DEMO and see the result:


This is a basic CSS animation. In this article, we’ll start with the sub-properties of animation and explore all aspects of CSS animation.


animation-name / animation-duration details


Overall, the individual animation-name and animation-duration don’t have a lot of tricks and are very well understood and put together.


First, let’s introduce animation-name . With animation-name , the CSS engine will find the corresponding @keyframes rule.


Of course, like CSS rule naming, it also has some tawdry operations. For example, he is supporting emoji emoticons, so the animation-name naming in the code can be written like this:

div {
    animation: 😄 3s;
}

@keyframes 😄 {
    0% {
        color: #f00;
    }
    100% {
        color: #000;
    }
}


While animation-duration sets the duration of a cycle of the animation, the above DEMO sets the overall duration of the animation to 3s , which is also very easy to understand.

 animation-delay


animation-delay It’s a bit more interesting, as it allows you to set the animation delay, which is the period of time between when the element is loaded and when the animation sequence starts executing.

 A simple DEMO:

<div></div>
<div></div>
div {
    width: 100px;
    height: 100px;
    background: #000;
    animation-name: move;
    animation-duration: 2s;
}

div:nth-child(2) {
    animation-delay: 1s;
}
@keyframes move {
    0% {
        transform: translate(0);
    }
    100% {
        transform: translate(200px);
    }
}


It is very intuitive to compare the following two animations, one with animation-delay added and one without:


The second div above, on the animation attribute, can also be abbreviated as animation: move 2s 1s , with the first time value indicating the duration and the second time value indicating the delay.

 animation-delay can be negative


The most interesting trick about animation-delay is that it can be negative. That is, although the name of the property is animation delay time, the animation can be advanced by applying a negative number.


Let’s say we want to implement a loading animation like this:

 There are several ways to think about it:


  1. Initially the 3 balls are positioned 120° apart and start rotating at the same time, but this is slightly more code intensive!

  2. Another way to think about it is that for the same animation, two of the three elements delay the whole animation by 1/3, 2/3 of the time.

 The core pseudo-code for Option 2 is as follows:

.item:nth-child(1) {
    animation: rotate 3s infinite linear;
}
.item:nth-child(2) {
    animation: rotate 3s infinite 1s linear;
}
.item:nth-child(3) {
    animation: rotate 3s infinite 2s linear;
}


However, for the first 2s of the animation, the other two elements won’t move, and only after 2s will the whole animation be what we want:


At this point, we can let the delay time of the 2nd and 3rd elements to negative values, so that the animation can be delayed -1s , -2s , that is, advance 1s , 2s :

.item:nth-child(1) {
    animation: rotate 3s infinite linear;
}
.item:nth-child(2) {
    animation: rotate 3s infinite -1s linear;
}
.item:nth-child(3) {
    animation: rotate 3s infinite -2s linear;
}


This way, each element doesn’t have to wait, it’s directly in motion, and the element spacing position is the result we want:


Building random effects with animation-duration and animation-delay

 One more interesting tip.


For the same animation, we utilize animation-duration randomized within a certain range and animation-delay randomized within a certain range, which can effectively build a more random animation effect and make the animation more natural.


I used this technique in both of the following pure CSS animations:

  1.   Pure CSS implementation of Huawei charging animation:
  1.   Pure CSS implementation of flame animation:


Take the pure CSS implementation of the Huawei charging animation as an example and explain it briefly.


Looking closely at this section, rising orbs one by one, leaving out some of the fusion effects here, and just focusing on the ever-rising orbs, it looks like there is no pattern to it:


Let’s simulate the core pseudo-code if we were to use 10 circles where both animation-duration and animation-delay agree:

<ul>
    <li></li>
    <!--共 10 个...--> 
    <li></li>
</ul>
ul {
    display: flex;
    flex-wrap: nowrap;
    gap: 5px;
}
li {
    background: #000;
    animation: move 3s infinite 1s linear;
}
@keyframes move {
    0% {
        transform: translate(0, 0);
    }
    100% {
        transform: translate(0, -100px);
    }
}

 This way, the movement of the little balls will be so neat and tidy:


To make the ball’s movement appear very random, just make both animation-duration and animation-delay float within a certain range, revamping the CSS:

@for $i from 1 to 11 {
    li:nth-child(#{$i}) {
        animation-duration: #{random(2000)/1000 + 2}s;
        animation-delay: #{random(1000)/1000 + 1}s;
    }
}


We use the loop of SASS and the random() function to let animation-duration be randomized in the range of 2-4 seconds, and let animation-delay be randomized in the range of 1-2 seconds. In this way, we can get very natural and different upward animation effects, which basically do not appear to be repeated, and simulate the random effect very well:

animation-timing-function


The jog function is very important in animation, it defines the rhythm at which the animation is executed in each animation cycle.

 Retardation is divided into two main categories:


  1. cubic-bezier-timing-function cubic-bezier-timing-function

  2. step-timing-function step-timing-function (this translation is my own, may be a bit strange)

 Cubic Bessel curve easing function


Let’s start by taking a look at the cubic Bezier curve jog function. In CSS, a number of jog function keywords are supported.

/* Keyword values */
animation-timing-function: ease; 
animation-timing-function: ease-in; 
animation-timing-function: ease-out; 
animation-timing-function: ease-in-out; 

 About the comparison of effects between them:


In addition to the 5 keywords supported by CSS, we can also customize the cubic Bezier curve using the cubic-bezier() method:

animation-timing-function: cubic-bezier(0.1, 0.7, 1.0, 0.1);


Here’s a very useful site — cubic-bezier for creating and debugging different parameters for generating Bessel curves.

 The effect of cubic Bezier curve easing on animation


Regarding the effect of jog functions on animation, here is a very good example. Here we have used pure CSS to implement a clock effect, for which the motion of the animation, if animation-timing-function: linear , has the following effect:


And if we I replace the jog function with animation-timing-function: cubic-bezier(1,-0.21,.85,1.29) , it has the following curve counterpart:


The entire animated rhythmic effect of the clock will turn out like this, with a completely different feel:


For many lean animations, the jog function is actually taken into account in the design. I came across a Physics-Based UX Design for Animation article a long time ago, but unfortunately I can’t find the original article today. Some of the concepts conveyed were that the design of animations is considered based on how they actually behave in life.


For example, linear is an unnatural motion when applied to certain animations because the uniform linear motion simulated by the program is difficult to achieve in real life due to the presence of air resistance. It is therefore difficult to build trust in a motion that is rarely perceived by the user. This kind of uniform linear motion is also something that we need to avoid when we are designing the dynamic effects.

 Step easing function


Next, we’ll talk about the step jog function. It is represented in CSS at animation-timing-function in the following ways:

{
    /* Keyword values */
    animation-timing-function: step-start;
    animation-timing-function: step-end;

    /* Function values */
    animation-timing-function: steps(6, start)
    animation-timing-function: steps(4, end);
}


In CSS, the most used step jog function is utilized for frame-by-frame animation. Suppose we have this image (image size 1536 x 256 , image from the web):


You can see that it’s actually 6 states of a character traveling, or 6 frames, and we can use animation-timing-function: steps(6) to link them together in a CSS animation, the code is very simple:

<div class="box"></div>
.box {
  width: 256px;
  height: 256px;
  background: url('https://github.com/iamalperen/playground/blob/main/SpriteSheetAnimation/sprite.png?raw=true');
  animation: sprite .6s steps(6, end) infinite;
}
@keyframes sprite {
  0% { 
    background-position: 0 0;
  }
  100% { 
    background-position: -1536px 0;
  }
}


To briefly explain the above code, first of all, it is important to know that just 256 x 6 = 1536 , so the above picture can actually be divided into just 6 segments:


  1. We set up a div of size 256px and gave the div a animation: sprite .6s steps(6) infinite animation;

  2. Where steps(6) means that the set @keyframes animation is divided into 6 executions (6 frames), and the overall animation time is 0.6s , so the pause length of each frame is 0.1s ;

  3. The animation effect is from background-position: 0 0 to background-position: -1536px 0 . Since the CSS code above does not set background-repeat , background-position: 0 0 is actually equivalent to background-position: -1536px 0 , which means that the image advances one round during the whole animation process, except that each frame stops at a characteristic place, a total of 6 frames;


Draw a simple diagram of steps 1, 2, and 3 above:


From the above figure, we can see that in the animation process, the value of background-position is only background-position: 0 0 , background-position: -256px 0 , background-position: -512px 0 and so on until background-position: -1536px 0 , due to the repeating property of the background, it just returns to the original point, and thus restarts a new round of the same animation.


So, the whole animation will be like this, each frame will stay 0.1s and then switch to the next frame (note that this is an infinite loop animation),:


For the full code you can poke here — CodePen Demo — Sprite Animation with steps()


animation-duration The effect of animation duration on animation


Insert another small section here, animation-duration The effect of animation length on animation is also very noticeable.


Based on the above code, we can make the walking effect into a running effect by modifying animation-duration and shortening each frame, and similarly, increase the dwell time of each frame. Make each step slow, as if you are walking.


It’s important to note that each frame, as described above, is not the same concept as each frame of FPS in the browser rendering process.


Look at the effect, the effect of setting different animation-duration (here it is 0.6s -> 0.2s), the GIF recording lost some keyframes, the actual effect will be a bit better:


Of course, in steps() , there is also the difference between steps(6, start) and steps(6, end) , that is, the difference between the keywords start and end . For the above infinite animation, in fact, is basically negligible, it is mainly to control the animation of the first frame of the start and duration, a relatively small point of knowledge, but want to understand the need for a relatively long space, limited to the content of this article, not to expand here, the reader can understand on their own.

 Comparison of interpolation and frame-by-frame animation renditions of the same animation effect


The three Bezier curve jogs and step jogs mentioned above are actually the corresponding fill-in animations and frame-by-frame animations.


For the same animation, sometimes both kinds of jogging are applicable. We need to analyze and select them when we use them.

 Suppose we implement such a graphic in CSS:


Now I want to use this graphic to create a Loading effect, and if I use fill-in animation, that is, three Bezier curve easing, to make it rotate, I get a very general effect:

.g-container{
    animation: rotate 2s linear infinite;
}
@keyframes rotate {
    0% {
        transform: rotate(0);
    }
    100% {
        transform: rotate(360deg);
    }
}

 The animation effect is as follows:


But if here, we replace the fill-in animation with frame-by-frame animation, because there are 20 points, so set to steps(20), and then look at the effect, you will get a completely different feeling:

.g-container{
    animation: rotate 2s steps(20) infinite;
}
@keyframes rotate {
    0% {
        transform: rotate(0);
    }
    100% {
        transform: rotate(360deg);
    }
}

 The animation effect is as follows:


The whole loading circle looks like it’s rotating, but it’s actually just 20 keyframes switching, which makes the overall effect feel more appropriate for the Loading effect.


Therefore, both animation effects are very necessary to master, in the actual use of the flexibility to try, choose the more suitable.


The full code for the above DEMO effect: CodePen Demo — Scale Loading steps vs linear

animation-play-state


Next, we talk about animation-play-state which, as the name suggests, controls the state of the animation — running or paused. It’s similar to starting and pausing a video player. It’s one of the limited means of controlling the state of an animation in CSS animation.

 It takes only two values (default is running):

{
    animation-play-state: paused | running;
}


It’s also very easy to use, see the example below where we pause the animation while hovering the button:

<div class="btn stop">stop</div>
<div class="animation"></div>
.animation {
    width: 100px;
    height: 100px;
    background: deeppink;
    animation: move 2s linear infinite alternate;
}

@keyframes move {
    100% {
        transform: translate(100px, 0);
    }
}

.stop:hover ~ .animation {
    animation-play-state: paused;
}


A simple CSS animation, but when we hover the button, add animation-play-state: paused to the animated element:


animation-play-state tip, pause by default, click run


Normally, it is very easy to use animation-play-state: paused in the normal way of thinking.


However, if we want to create some interesting CSS animation effects, we might as well do the opposite.


We all know that under normal circumstances, animation should be running, so if we set the default state of some animation to pause, only when the mouse clicks or hover, then set its animation-play-state: running , so you can get a lot of interesting CSS effects.


Look at an example of pouring wine, this is a pure CSS animation, but by default, the animation is at animation-play-state: paused , that is, the state of pause, only when the mouse clicks on the cup, then set animation-play-state: running , so that the wine is poured, the use of animation-play-state to achieve a very interesting interactive effect:


For the full DEMO you can poke here: CodePen Demo — CSS Beer!


We can see this technique in a lot of Web creative interaction animations.


  1. After the page is rendered, the animation will not start without any action. The animation only starts when the mouse is given the animation animation-play-state: running by triggering the element’s :active pseudo-class effect at click ;

  2. The animation stops when the mouse stops clicking and the pseudo-class disappears at any point in the animation;


animation-fill-mode Controls the state of the element at each stage.


The next attribute, animation-fill-mode , is mistakenly thought by many to be used only to control whether an element is reset at the end of an animation. This is actually inaccurate and incomplete.

 Look at the values it takes:

{

    animation-fill-mode: none;
    
    animation-fill-mode: backwards; 
   
    animation-fill-mode: forwards;    
 
    animation-fill-mode: both; 
}


For the animation-fill-mode interpretation, I came across 4 good interpretations in a Q&A on Segment Fault (SF – How to understand animation-fill-mode), which I’ll borrow here:

 Suppose the HTML looks like this:

<div class="box"></div>

 The CSS is as follows:

.box{
    transform: translateY(0);
}
.box.on{
    animation: move 1s;
}

@keyframes move{
    from{transform: translateY(-50px)}
    to  {transform: translateY( 50px)}
}


Use the image to represent the value of translateY as a function of time:


  • The horizontal axis is the time, when it is 0, it means the time when the animation starts, that is, the time when the on class name is added to the box, one frame of the horizontal axis means 0.5s.

  • The vertical axis indicates the value of translateY , and a value of 0 indicates that the value of translateY is 0. One cell of the vertical axis indicates the value of 50px
  1.   animation-fill-mode: none The performance is shown in the figure:


To summarize, outside of animation time, an element’s style is limited only by its CSS rules, and has nothing to do with the definition of keyframes within @keyframes.

  1.   animation-fill-mode: backwards The performance is shown in the figure:


To summarize, the element is styled as the first frame of the animation before the animation starts (including the untriggered animation phase and during the animation-delay period), and after the animation ends, it is styled back to the style set by the CSS rules.

  1.   animation-fill-mode: forwards The performance is shown in the figure:


To summarize, the style of an element before the animation starts is the style set by the CSS rules, while the style after the animation ends is represented by the value calculated from the last keyframe encountered during the execution (i.e., stopping at the last frame).

  1.   animation-fill-mode: both The performance is shown in the figure:


A one-sentence summary that combines the settings of animation-fill-mode: backwards and animation-fill-mode: forwards . The style before the animation starts is the first frame when the animation runs, and stops at the last frame when the animation ends.

animation-iteration-count/animation-direction


Having talked about animation-fill-mode , we can drop in a few words about two of this better-understood attributes — animation-iteration-count and animation-direction


  • animation-iteration-count Controls the number of times the animation runs, either as a number or infinite , note that numbers can be decimals

  • animation-direction Control the direction of the animation, forward, reverse, forward alternate and reverse alternate


When talking about animation-fill-mode above, I used the term first frame of an animation run instead of the first frame defined in @keyframes, because the actual state of the first and last frames of an animation run is also affected by the direction of the animation run, animation-direction and animation-iteration-count .


In CSS animation, animation-iteration-count and animation-direction together determine the state of the first and last frames of an animation run.

  1.  The first frame of the animation run is determined by animation-direction

  2. The last frame of the animation run is determined by animation-iteration-count and animation-direction


The last frame of the animation, that is, the final state of the animation, and we can use animation-fill-mode: forwards to let the animation stay in this frame after the end, this is still relatively good to understand, but the relationship between animation-fill-mode: backwards and animation-direction is very easy to get confused, here is a brief explanation.


Set a slider of 100px x 100px in a container of 400px x 100px with the following code:

<div class="g-father">
    <div class="g-box"></div>
</div>
.g-father {
    width: 400px;
    height: 100px;
    border: 1px solid #000;
}
.g-box {
    width: 100px;
    height: 100px;
    background: #333;
}

 The performance is as follows:


Then, after adding animation , the initial and end states of the animation will be different under different animation-iteration-count and animation-direction effects.


If animation-fill-mode: backwards is set, the state of the element before the animation is started is determined by animation-direction :

.g-box {
    ...
    animation: move 4s linear;
    animation-play-state: paused;
    transform: translate(0, 0);
}
@keyframes move {
    0% {
        transform: translate(100px, 0);
    }
    100% {
        transform: translate(300px, 0);
    }
}


Note that in the CSS rule here, the element does not set the displacement transform: translate(0, 0) , while in the animation, the translateX of the first keyframe and the last key are 100px and 300px , respectively, together with the different animation-direction initial state as follows.


The following figure assumes that we have set the animation to be paused by default — animation-play-state: paused , then the state of the animation before it starts is:

 Partitioning and reuse of animations


Having talked about each property, let’s look at some of the details of the animation usage process.

 Look at an animation like this:

<div></div>
div {
    width: 100px;
    height: 100px;
    background: #000;
    animation: combine 2s;
}
@keyframes combine {
    100% {
        transform: translate(0, 150px);
        opacity: 0;
    }
}


Here we have implemented a div block drop animation that changes transparency as it drops:

 For such an animation with multiple property changes, it is actually equivalent:

div {
    animation: falldown 2s, fadeIn 2s;
}

@keyframes falldown {
    100% {
        transform: translate(0, 150px);
    }
}
@keyframes fadeIn {
    100% {
        opacity: 0;
    }
}


In the CSS animation rules, animation is able to receive multiple animations, not only for reuse, but also for the purpose of partitioning, so that we can have more precise control over the animation at each property level.

 Keyframes Rule Setting


We often see the following two CSS @keyframes settings in various CSS codes:

  1.  Percentage of use
@keyframes fadeIn {
    0% {
        opacity: 1;
    }
    100% {
        opacity: 0;
    }
}
  1.  Use from and to
@keyframes fadeIn {
    from {
        opacity: 1;
    }
    to {
        opacity: 0;
    }
}


In the definition of the CSS animation @keyframes , from is equivalent to 0% , and to is equivalent to 100% .


Of course, when we have more than 2 keyframes, it is more recommended to use the percentage definition.


In addition, the frames animation-fill-mode , 0% and from can be deleted when the animation’s start frame is equal to the value given in the CSS rule and is not set.

 High Prioritization of Animation States


I’ve talked about an interesting CSS phenomenon in this post – Cascading in CSS (Cascading Style Sheets).


This is one of the misconceptions that many people have about CSS prioritization, which also takes into account the cascading (cascading) order of selectors in CSS.


Which value to use depends on the priority of the style only if the cascade order is equal.

 And what is the cascade order?


According to the latest CSS Cascading 4 standard:


The priority of the cascading order of assertions under the current specification of the definition is as follows (the further down the hierarchy the higher the priority, the following rules are in ascending order):

  • Normal user agent declarations
  • Normal user declarations
  • Normal author declarations
  • Animation declarations
  • Important author declarations
  • Important user declarations
  • Important user agent declarations
  • Transition declarations

 A brief translation:

 According to the above algorithm, it’s probably like this:


Styles for each frame during transition animation > !important styles set by user agent, user, page author > Style priority for each frame during animation > Page author, user, user agent normal styles.


However, after testing with multiple browsers, this is not actually the case. (Embarrassed)


As an example, we can use this feature to override the !important style in the in-line style:

<p class="txt" style="color:red!important">123456789</p>
.txt {
    animation: colorGreen 2s infinite;
}
@keyframes colorGreen {
    0%,
    100% {
        color: green;
    }
}


In Safari browser, the color of the above DEMO text is green, that is to say, in the animation state of the style, can override the line style of !important style, belongs to the highest priority of a style, we can through infinite animation, or animation-fill-mode: forwards , using this technique, override the line style of !important style should be a very very high priority.


I was able to get the same result in Chrome two years earlier, but as of today (2022-01-10), the latest version of Chrome no longer supports the feature !important where the keyframe style priority overrides the in-line style during animation.


For different browsers, you can try it yourself with my DEMO, CodePen Demo – the priority of CSS Animation.

 CSS Animation Optimization

 This is a point of great concern to a very large number of people.

 My CSS animation is jerky, how should I go about optimizing it?


Animation elements generate separate GraphicsLayer, forcing GPU acceleration to start


CSS animation is very laggy is actually a description of the phenomenon, its essence is actually in the animation process, the browser refresh rendering page frame rate is too low. Generally speaking, most browsers have a refresh rate of 60 times/second, so usually speaking, the animation is better when the FPS is 60 frame/s, which means that the consumption time of each frame is 16.67ms.


When the page is in animation change, we feel the lag of the page when the frame rate is below a certain value.


The reason for the low frame rate is that the browser handles too many things between frames, more than 16.67ms, to optimize the time of each frame, but also need to know what the browser did in each frame, this involves the cliché browser rendering page.


To this day, while the rendering process isn’t exactly the same across browsers, it’s basically pretty much the same, basically:

 Simplified it’s also this diagram:

 These are two charts that you can see in very many different articles.


Returning to the focus of this article, a large part of the overhead of Web animation is layer redrawing, and the layer-based composite model has a profound effect on rendering performance. When drawing is not required, the overhead of composite operations is negligible, so when trying to debug rendering performance issues, the primary goal is to avoid layer redraws. This then gives direction to performance optimization of animations by reducing element redraws and reflows.


In this case, how to minimize the page reflow and redraw, here we will use what we often call ** GPU acceleration **.


The essence of GPU acceleration is to reduce the amount of reflow and repaint during each frame of the browser’s rendering of the page, which, at its root, is to allow elements that need to be animated to generate their own GraphicsLayer.


When a browser renders a page, it uses a number of intermediate representations that are not exposed to the developer, the most important of which are layers.


In Chrome, there are different types of layers: RenderLayer (responsible for the DOM subtree), and GraphicsLayer (responsible for the subtree of the RenderLayer).


GraphicsLayer, which is very important for our web animations, is a layer that Chrome usually paints into a bitmap before uploading it to the GPU as a texture. If the content doesn’t change, there’s no need to repaint the layer.


When an element generates its own GraphicsLayer, Chrome doesn’t always redraw the entire layer during the animation process, it tries to intelligently redraw the part of the DOM where the animation occurs, where it fails. Before Composite, the page was in a layered state, and with the help of the GPU, the browser redraws the layer of the element with its own independent With the help of the GPU, the browser only redraws the GraphicsLayer element layer at each frame, which greatly reduces the overhead of rearranging and redrawing the entire page and improves the efficiency of page rendering.


Therefore, the first rule of optimization for CSS animation (and web animation as well) is to make the elements that need to be animated generate their own independent GraphicsLayer, forcing the start of GPU acceleration, and we need to know that the essence of GPU acceleration is to use the elements to generate their own independent GraphicsLayer, reducing the page redrawing and rearranging the page during the rendering process overhead. The essence of GPU acceleration is that it reduces the overhead of redrawing and rearranging the page during the rendering process by having the elements generate their own independent GraphicsLayer.


Of course, there are very many more ways to generate your own standalone GraphicsLayer than just the transform3d api. For a large and very roundabout section above, you can take a look at these articles again:

 


In addition to the above guidelines, there are some suggestions for improving the performance of CSS animations:

 Reduced use of performance styles


Different styles are different in terms of consuming performance, and changing some properties has more overhead than changing others, and is therefore more likely to make the animation stutter.


For example, changing an element’s box-shadow would require a much more expensive drawing operation than changing the element’s text color. box-shadow Attributes, from a rendering perspective, are very performance intensive because their drawing code takes too long to execute compared to other styles. This means that if a heavily performance-intensive style requires frequent redraws, you’re going to have a performance problem.


Similarly, CSS 3D transforms, mix-blend-mode , filter , are more performance intensive than other simple operations. We should try to minimize their use during animation or find alternatives.


Of course, nothing stays the same; styles that perform poorly today may be optimized tomorrow, and there are differences between browsers.


So the key is to use the developer tools to identify the performance bottlenecks for each instance of lagging, and then try to reduce the browser’s workload. It’s important to learn the Performance panel and other rendering-related panels of the Chrome Developer Tools, but that’s not the focus of this article. That’s not the focus of this article, but you can explore it on your own.


Use will-change to improve rendering performance for page scrolling, animations, etc.


will-change Provides a way for web developers to tell the browser what is going to happen to the element, so that the browser can prepare for optimizations before the element’s attributes actually change. This optimization prepares some of the complex calculations in advance, making the page more responsive.

 It’s worth noting that it’s not easy to use this attribute:


  • Don’t apply will-change to too many elements: browsers have done their best to try to optimize everything they can. There are some more powerful optimizations that, when combined with will-change, have the potential to consume a lot of machine resources and, if overused, can result in pages that are slow to respond or consume a very large amount of resources.


  • Used in moderation: Normally, when an element is restored to its initial state, the browser discards the optimization work done earlier. However, if the will-change attribute is explicitly declared directly in the stylesheet, it indicates that the target element may change frequently, and the browser will save the optimization work for longer than before. So the best practice is to switch the value of will-change via script before and after the element changes.


  • Don’t apply will-change optimizations too early: if your page has little to no performance issues, don’t add the will-change attribute to squeeze a tiny bit of speed out of it. will-change It was originally designed to be used as a last resort optimization to try to solve existing performance problems. It should not be used to prevent performance problems. Excessive use of will-change will result in a large memory footprint and will lead to a more complex rendering process as the browser tries to prepare for the change process that may be present. This can lead to more serious performance problems.


  • Give it enough time to work: This attribute is used to allow the page developer to inform the browser which properties are likely to change. The browser can then choose to do some optimization work in advance before the change occurs. So it’s important to give the browser time to actually do the optimization work. To use this, you need to try to find some way to be notified of possible changes to an element some time in advance, and then add the will-change attribute to it.


Some say will-change is good medicine, others say it’s poison, and when it comes to specific uses, you can test it more.

By lzz

Leave a Reply

Your email address will not be published. Required fields are marked *