Why is the animation jerky on the web page?

Saravanan A R
4 min readOct 14, 2020

In this post, I’ll talk about web animation. I split this post into two-part.

  1. How does the animation work in the browser?
  2. Why is the animation jerky in the browser?

How does the animation work in the browser?

Web animation works as same as native animation. Let’s say a box is moving from a point A to B in 200 ms.

In CSS, we give the start point A, the endpoint B, and the duration for the animation. Here, I used the CSS animation keyframe. Below is the code snippet.

We are telling the browser that the box is at the position A(left = 0px) at 0ms and the browser should display the box at the position B(left = 500px) at 200 ms.

What will the browser do in the time interval between 0 and 200 ms? The browser will interpolate(calculate) the position of the box at each frame and it will paint the box at the calculated position.

I will talk more about the “frame” in the context of the browser at the end. As of now, just assume, frame means 16 ms time interval.

So, now divide the total time for the box animation(200 ms) into a set of 16 ms time frames.

200 ms / 16 ms = ~12 frames.

We have a set of 12 frames which means that the browser has to paint the box 12 times at 12 different positions to give us a smooth animation feel.

Changing the arithmetic(layout) too often will make the browser paint again and again.

Reducing the browser paint time should be the goal. As we all know, Web page javascript runs on a single-threaded engine. Creating an application with 60fps is a great task.

2. Why is the animation jerky in the browser?

Now you know how the animation works. In this part, I’ll talk about the performance of the animation. Have you ever saw a jerky animation on the web page? Like the one below.

Have you ever thought why is the jerk happening? Whether you animate using JS or CSS, it doesn’t matter, an animation is a tedious task for the browser.

Before understanding the reason for the jerky animation, you need to understand the Browser Frames.

A frame is a collection of browser jobs at the moment. Those jobs include running the js scripts and painting the changes on the screen.

If you don’t understand, don’t worry. Just continue reading. You’ll get a clear picture at the end.

If the frame is a collection of jobs, you may have a question why did I represent a frame as 16 ms? Because for an idle case, all those jobs should be done in a 16ms.

Let’s see an example, this will give you a clear picture.

Consider the above image, if you click the button “render”, the browser will display the text “Hello, world”. The code snippet for the above image is given below:

a) The button’s on-click event will invoke a function renderHello().

b) renderHello() will set the CSS property of the div.

c) This will make the browser recalculate its style and layout.

d) Finally, the browser will paint the text on the screen.

This constitutes a frame. All the above-mentioned jobs should run within 16ms. This is not a big task for the browser.

Now, change the above renderHello() as:

This will become a tedious task for the browser to complete the set of jobs within 16 ms. Let’s say the renderHello() function takes 2 seconds to complete until that the browser won’t display “Hello, World” text on the screen.

Now, the flow will be,

a) The button’s on-click event will invoke a function renderHello().

b) renderHello() runs a while loop until “i” become 1 million(1000000). Consider, this loop takes 2 seconds to complete.

c) Once the while loop complete, it changes the “display” property.

d) Finally, the browser will paint the text on the screen.

Now, go back to our box animation, we have a set of 12 frames(16 ms) to move a box from A to box B. The 12 positions of the boxes are X1, X2, X2, …., X12.
Consider the box is at the position X6 (6th frame), at that moment, the user is clicking a button which causes the renderHello() function should invoke. Now the browser has to do the following jobs within 16 ms to attain an idle case.

  1. Run the renderHello()
  2. Paint the box at the next position

Let’s say the renderHello() takes 64 ms to complete. Now the browser has to skip the next four positions(X7, X8, X9, X10) and should paint the box at position X11 in order to complete the animation within the assigned duration which is 200 ms. These skips cause the animation to jerky.

Missing frames make the animation jerky.

--

--