Animation development — CSS and JavaScript



CSS3 transition is the effect of changing elements from one style to another

value describe
transition-property Specifies the name and transition effect of the CSS property
transition-duration How many seconds or milliseconds does the transition effect take to complete
transition-timing-function Specifies the speed curve for the transition effect
transition-delay Define when the transition effect starts


value describe
none No properties get a transition effect.
all All properties will have a transition effect.
property Defines a comma separated list of CSS property names to which transition effects are applied.


value describe
linear Specifies the transition effect from beginning to end at the same speed (equal to cubic Bezier (0,0,1,1)).
ease The transition effect (cubic Bezier (0.25,0.1,0.25,1)) is defined as slow start, then fast, and then slow end.
ease-in The transition effect (equal to cubic Bezier (0.42,0,1,1)) starting at slow speed is specified.
ease-out The transition effect (equal to cubic Bezier (0,0,0.58,1)) with slow end is specified.
ease-in-out The transition effect (equal to cubic Bezier (0.42,0,0.58,1)) with slow start and end is specified.
cubic-bezier(n,n,n,n) Define your own values in the cubic Bezier function. The possible values are values between 0 and 1.


Create animation

value explain
animation-name Specifies the name of the keyframe to bind to the selector
animation-duration The animation specifies how many seconds or milliseconds it takes to complete
animation-timing-function How does animation complete a cycle
animation-delay Sets the delay interval before the animation starts.
animation-iteration-count Defines the number of times the animation plays.infiniteSpecifies that the animation should play infinitely (forever)
animation-direction Specifies whether the animation should play backwards in turn.
animation-fill-mode Specifies the style to be applied to an element when the animation is not playing (when the animation is finished, or when the animation has a delay that does not start playing).
animation-play-state Specifies whether the animation is running or suspended.


value describe
linear The speed of the animation is the same from beginning to end.
ease Default. The animation starts at a low speed, then speeds up and slows down before it ends.
ease-in The animation starts at a low speed.
ease-out The animation ends at a low speed.
ease-in-out The animation starts and ends at a low speed.
cubic-bezier(n,n,n,n) In the cubic Bezier function. The possible values are values from 0 to 1.


value describe
normal Default value. The animation plays normally.
reverse The animation plays backwards.
alternate The animation plays forward in odd number of times (1, 3, 5…) and backward in even number of times (2, 4, 6…).
alternate-reverse The animation plays backward in odd number of times (1, 3, 5…) and forward in even number of times (2, 4, 6…).


value describe
none Default value. The animation does not apply any styles to the target element before and after the animation is executed.
forwards At the end of the animation (determined by animation iteration count), the animation applies the attribute value.
backwards The animation is applied to the attribute values defined in the keyframe of the first iteration that starts the animation during the animation delay definition. These are the values in the from keyframe (when the animation direction is “normal” or “alternate”) or the to keyframe (when the animation direction is “reverse” or “alternate reverse”).
both Animation follows the rules of forwards and backwards. That is to say, animation extends animation attributes in two directions.


value describe
paused Specify pause animation
running Specifies the animation that is running

Browser event cycle mechanism

Behind the browser interface, there are many event execution mechanisms that users can’t perceive, including loading resources, rendering, network request, user interaction and other behaviors. Animation is also a part of them, because we can’t control the priority order of behaviors. Understanding these mechanisms is good for developing how to use animation better

  1. All tasks are run on the main thread to form an execution stack
  2. Synchronous tasks directly execute and block subsequent tasks to wait for the end. When some asynchronous tasks are encountered, a new thread will be opened to execute the task and then execute it down. After the asynchronous tasks are executed, the callback event will be added to theTask queue
  3. WhenExecution context stackWhen all the tasks are finished, we’ll arriveTask queueExtract all of them from the libraryMicro tasksAfter the event is executed, if a new micro task is added to the execution of the micro task, it will also be executed together in this step;
  4. At the end of a cycle, the GUI rendering thread takes over the check to detect whether there is a rendering opportunity. The rendering opportunity is determined according to the physical environment (depending on the performance of the machine, the screen refresh rate, page performance and whether the page is running in the background);

    • The browser will keep the frame rate as stable as possible. For example, if the page performance cannot maintain 60fps (rendering every 16.66ms), the browser will choose the update rate of 30fps instead of losing frames occasionally.
    • If the browser context is not visible, the page will be reduced to about 4 FPS or even lower.
    • Even if the above conditions are met, it is possible to skip rendering

      a. The browser judges that updating the rendering will not bring visual changes.

      b. Frame animation callback is empty

  5. If you do not render in this round, the following operations will not be performed. Multiple tasks will be merged into the next round when they can be rendered, which is also conducive to optimizing the rendering consumption caused by the merging or overlapping of their states, and offsetting each other
  6. For documents that need to be rendered,

    • If the size of the window changes, the monitor is executedresizemethod.
    • If the page scrolls, executescrollmethod.
    • Perform a frame animation callback, that isrequestAnimationFrameThe callback of the.
    • implementIntersectionObserverThe callback of the.
  7. Re render the user interface.
  8. Determine whether the asynchronous queues are all empty, and if so, proceedIdleIdle cycle algorithm to determine whether to executerequestIdleCallbackThe callback function of.

The browser may assign three-quarters of the priority to user interaction behavior (mouse and keyboard events) on the premise of maintaining the task order, so as to ensure that the user’s input gets the highest priority response, and the remaining priority is given to other usersTaskAnd make sure they don’t starve to death.

aboutresizeandscrollFor example, scrolling and zooming are not performed at this stage. The browser will save onepending scroll event targets, wait until thescrollThis step is to send an event to the corresponding target and drive it to execute the callback function of listening.resizeThe same is true.


 * you want to perform an animation and ask the browser to update the animation by calling the specified callback function before the next repainting.
 * @param callback
 *@ return request ID
callback The function called to update the animation frame before the next redraw. The callback function is passed inDOMHighResTimeStampParameter, which is the same as return value of is the same as that ofrequestAnimationFrame()The time when the callback function starts to execute.
Return value A long integer, request ID, is the only identifier in the callback list. It’s a non-zero value. It doesn’t make any sense. You can pass this value towindow.cancelAnimationFrame() To cancel the callback function.

The number of callbacks is usually 60 per second, but in most browsers that follow W3C recommendations, the number of callbacks usually matches the number of browser screen refreshes. In order to improve performance and battery life, in most browsers, whenrequestAnimationFrame()Running in the Background tab or hiddeniframeWhen I’m in the car,requestAnimationFrame()Will be suspended to improve performance and battery life.

The callback function is passed inDOMHighResTimeStampParameters,DOMHighResTimeStampIndicates that the currentrequestAnimationFrame()The time when the sorted callback function is triggered. For multiple callback functions in the same frame, each of them will receive the same timestamp, even though some time has been consumed during the workload calculation of the previous callback function. The time stamp is a decimal number in milliseconds with a minimum accuracy of 1 ms (1000 μ s).

DOMHighResTimeStampIs a double type used to store time values. The value can be a discrete point in time or the time difference between two discrete points in time. The unit of T is milliseconds, which should be accurate to 5 microseconds. However, if the browser is unable to provide a time value accurate to 5 microseconds (for example, due to hardware or software limitations), the browser can express the value in milliseconds in milliseconds.

Request animation frame vs timer

Let’s use two APIs to achieve the same animation effect and see how they perform


const gap = 16.6
let num = 0
let timer

function run() {
    timer = setTimeout(() => {
        num++ = num % 2 ? "red" : "blue"
        num < 30 && run()
    }, gap)

Animation development -- CSS and JavaScript


let num = 0

function run() {
    window.requestAnimationFrame(() => {
        num++ = num % 2 ? "red" : "blue"
        num < 30 && run()

Animation development -- CSS and JavaScript


SetTimeout does not draw. Visually, it is a frame dropping situation, while request animation frame will draw the interface regularly. The reason is that in general, the frame rate of the browser is the same as that of the screen, which is basically 60, In other words, the timer will refresh once every 16 Ms. the timer only adds the corresponding task to the processing queue after timing, and still has to wait until the execution stack is idle to extract the queue for execution. The result is that

  • If the timer time is less than the frame rate, several timer callbacks have been performed before the next rendering
  • The timer callback will be blocked by other tasks in the main thread, and each time error will affect the subsequent execution time

These two effects cause the timer animation will often pass frame or abnormal rate

RequestAnimationFrame is called before the browser redraws next time, that is, the timing of the call is guaranteed by the system itself, which can guarantee the execution in idle time. Another advantage is that when the page is switched to other applications or hidden, it will suspend the call to improve the performance and battery life.

There is another timer, setinterval, which has some problems

  • Cumulative effect: if the execution stack blocking time is long enough that there are multiple setinterval corresponding tasks in the queue, the execution time will be far less than the expected result of developers;
  • Some browsers (such as Safari, etc.) execute JS during scrolling, which is easy to cause stuck and unknown errors;
  • When the browser is minimized, setinterval will continue to execute, but the corresponding tasks will be executed at the moment when the browser is restored;

Requestidlecallback (in experiment)

This function is still under development in some browsers. Please refer to the browser compatibility table to get the prefix suitable for different browsers. Because the standard document corresponding to the function may be revised, the syntax and behavior of the function may change in the future version of the browser.

 *Queue functions that are called during the idle period of the browser
 * @param callback
 * @param options 
window.requestIdleCallback(callback[, options])
callback A reference to a function that will be called when the event loop is idle. The function receives aIdleDeadlineThis parameter can obtain the current idle time and whether the callback has been executed before the timeout.
Options (optional) timeout: if timeout is specified and has a positive value, and the callback has not been called through the timeout milliseconds, the callback will be enforced in the next idle period, although this is likely to have a negative impact on performance.

React implements a similar time slicing rendering mechanism


The web development and use of this API can coordinate the scheduling of background tasks, so that they will not bring any other high priority tasks sharing the same cycle stage, such as input processing, animation and frame synthesis. User agents can better understand when they are suitable for running background tasks based on what they know about the current scheduling tasks, Vsync latency, user interaction and so on. Therefore, when the browser will be idle, using this API can schedule background tasks more appropriately

Idle period

After the input processing, rendering and composition are completed in a given frame, the main thread of the user agent is usually idle until the next frame starts, and another waiting task is qualified to participate in the running. Or it receives user input. This specification provides a way to schedule and execute callbacks through the requestidlecallback API at other idle times

Through the way of requestidlecallback API callback, it can be executed in the idle period defined by the user agent. It will give a corresponding deadline corresponding to the end time of the current idle period. This determines how the user agent defines the composition of the idle period, but it is expected that they will occur in the static period, and the browser is in the idle period

An example of an idle cycle is when a dynamic animation is in the time between submitting a given frame to the screen and starting processing the next frame

Figure 1 Example of an inter-frame idle period

Animation development -- CSS and JavaScript

During dynamic animations and screen updates, such idle times occur frequently, but are usually very short (i.e., devices less than 16 ms have a vertical synchronization period of 60 Hz)

be careful

Some operations, such as promise parsing or triggering page layout, may cause subsequent tasks to be scheduled only after the idle cycle is completed. In this case, the, The application should do this extra work before the deadline, allowing it to be performed before the next framework deadline.

Figure 2 Example of an idle period when there are no pending frame updates

Animation development -- CSS and JavaScript

Another example is that the user agent does not update the screen during the idle period. In this case, the user agent may not have the subsequent tasks that can be bound to the end of the idle period, so as to avoid causing the user’s perceptible delay in unpredictable tasks. For example, the length of the idle time should be limited to the maximum value of 50ms for user input processing, Once an idle cycle has been completed, the user agent can immediately schedule another idle cycle (if it remains idle), as shown in Figure 2, so that the background work can continue to occur for a longer idle time.

In the idle cycle, the user agent will run callbacks in the first in first out order until the end of the idle cycle or no more idle callbacks are qualified to run. As for itself, the user agent does not need to run all the currently published idle callbacks in one idle cycle. Any remaining idle tasks can be run in the next idle period.

be careful

To provide developers with the best performance, encourage the elimination of unnecessary callbacks (such as request animation frame, setTimeout, etc.), they do not perform meaningful work, do not keep these callbacks triggered and wait for the response of events. Instead, schedule them as needed to respond to events when they are available, This mode improves the overall efficiency and allows the user agent to schedule long idle cycles (up to 50ms), which can be used to efficiently perform large blocks of background work.

Because it’s not standardized yet, update details can be viewedhere