“Dirty” elements in web development

These are the elements that have been modified and their child elements.

If we somehow changed the block, the browser will redraw it and its children, because their position and size may depend on the parent.

The tree of “dirty” and redrawn elements

Then the browser proceeds to, in fact, rendering.

Directly rendering, Paint

During rendering (Paint), the browser fills the pixels on the screen with the desired colors, depending on what should be drawn in a particular place: text, image, background color, shadows, frames, etc.

Rendering can also be global and incremental. To understand which part of the viewport needs to be redrawn, the browser divides the entire viewport into rectangular sections. The logic here is the same as in Layout — if the changes are limited to one section, then it will be marked “dirty” and only it will be redrawn.

Rendering is the most expensive process of all that we have already listed.

Drawing order

The order of rendering is related to the stack context.

In general terms, the rendering starts from the background and gradually moves to the foreground:

  • background-color;
  • background-image;
  • border;
  • children;
  • outline.

CPU and compositing

And Layout and Paint work at the expense of the CPU (central process unit), therefore relatively slow. Smooth animations in this scenario are incredibly expensive.

For smooth animations in browsers, Compositing is provided.

Compositing is the division of the page content into “layers” that the browser will redraw. These layers do not depend on each other, which is why changing an element in one layer does not affect elements from other layers, and it becomes unnecessary to redraw them.

It is because of the separation of elements into different composite layers that the transform property does not load the browser so much. Therefore, in order not to slow down animations, it is recommended to do them using transform and opacity.

Compositing scheme

The use of properties such as, for example, transform, “puts” the element on a separate composite layer, where the position of the element does not depend on others and does not affect them.

📝

To find out if a particular CSS property causes compositing and redrawing in the browser, use the CSS Triggers tool.

Redrawing, Reflow (relayout) and Repaint

Section of the article “Redrawing, Reflow (relayout) and Repaint”

The rendering process is cyclical. The browser redraws the screen every time some changes occur on the page.

If, for example, a new node has been added to the DOM tree, or the text has changed, the browser will build a new rendering tree and start calculating the position and rendering again.

One update cycle is the animation frame.

Knowing the browser’s “rendering schedule”, we can “warn” it that we want to run some kind of animation on each new frame. This can be done using requestAnimationFrame().

const animate = () => {

  // Animation code

}

Copy

This function starts a new animation frame: updates some property or redraws the canvas.

If we want to achieve smooth animation using the function above, we need to provide an average of 60 screen updates per second (60 fps — frames per second).

This can be done clumsily, after an interval:

// 60 times in 1000 milliseconds, approximately 16 ms.

const intervalMS = 1000 / 60

setInterval(animate, intervalMS)

Copy

Or use window.requestAnimationFrame():

window.requestAnimationFrame(animate)

Copy

Intervals are not always triggered at the right moment. setInterval() does not take into account at what stage of rendering the page is, and as a result, the rendering frames may be torn or jerky:

With an interval, the animation may be torn, because the redrawing may be started at the wrong time.

And if the tab was inactive, then the interval can “try to catch up with time”, and several frames will start at once:

  ….|….|..||…|….|………||||..|….|…|…|….|…

With requestAnimationFrame(), the animation is smoother because the browser knows that in the next frame, you need to start a new animation frame.

It does not guarantee that the animation will be run strictly once every 16 ms, but the value will be close enough.

  ….|….|….|…|….|…|….|….|…|…..|….|….

In practice

Sasha Bespoyasov advises

The section of the article “Sasha Bespoyasov advises”

Always use transform and opacity for dynamics, avoid changing other properties (such as left, top, margin, background, and so on).

This way you will give the browser the opportunity to optimize the rendering, which will make the page more responsive.

For animations that need to be redrawn on each frame, use requestAnimationFrame().

This will make heavy animation less ragged.

– Collapse

Leave a Reply

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