Let’s start with a couple of questions

  1. What are layers?
  2. What role do layers play in browser rendering?
  3. How does the browser draw layers?
  4. What does the GraphicsLayer Tree do?
  5. In page optimization, when you’re writing code, how do you optimize with layers? (CSS only, not JS code)
  6. Why do CSS animations still work when some pages are stuck?

Browser rendering process

In this section I describe what layers are and the role they play in browser rendering.

The process of rendering a page by the browser

Before we talk about layering, let’s go over the general process of generating a browser render:

  1. Build a DOM tree

    • HMTLLexical analysis, into the correspondingAST
  2. Style calculation:

    • Converting CSS to a structure that browsers can understand can be viewed in Document.stylesheets

    • Format style attributes such as REM -> px, white -> #FFFFFF, etc

    • Compute the style properties of each node: Build the Render tree with the DOM tree based on the CSS selector

  3. Generate layout tree

    • Let me get rid of some of thatdisplay: noneHide style elements as they are not presentrenderIn the tree
  4. Create layer tree (Layer)

    • It is mainly divided into”Explicit synthesis“And”Implicit synthesis
      • When redrawing, you only need to redraw the current layer
  5. Layer to draw

    • Convert the layer tree into a list of instructions to draw
  6. Rasterization (rasterization)

    The so-called rasterization is to convert a map block into a bitmap.

    • The drawing list is delivered to the composition thread for layer partitioning, which is called partitioning.
    • A rasterized thread pool is maintained in the rendering process, which is responsible for transferring blocks toGPUApply colours to a drawing
    • GPUAfter rendering, bitmap information is passed to the compositing thread, which displays the bitmap information on the display
  7. Composition and display

So the Layer is the Layer

👆🏻 above is the browser rendering process, we will focus on step 4 this time.

If we separate out the red area, it looks something like this:

Basic concept

Here are four additional concepts:

  1. RenderObject

    A DOM node corresponds to a render object, which maintains the tree structure of the DOM tree. The render object knows how to draw the content of the DOM node by issuing the necessary draw instructions to a GraphicsContext.

  2. RenderLayer

    As the first layer model constructed in browser rendering, rendering objects in the same coordinate space of the same level are merged into the same rendering layer. Therefore, according to the cascading context, rendering objects in different coordinate space of different levels will form multiple rendering layers to reflect the cascading relationship between them. Therefore, browsers automatically create new layers for rendered objects that meet the conditions for forming a cascading context. In general, there are several common situations that will cause the browser to create a new render layer for it:

    • documentThe element
    • position: relative | fixed | sticky | absolute
    • opacity < 1
    • will-change | fliter | mask | transform ! = none | overflow ! = visible
  3. Graphics Slayer

    The Graphics layer is a layer model that is responsible for generating the content graph that is finally ready to be rendered. It has a GraphicsContext that is responsible for the output of the bitmap of the layer. The bitmap stored in the shared memory will be uploaded to the GPU as a texture (think of it as a bitmap image moved from main memory to image memory). Finally, the GPU will synthesize multiple bitmaps and draw them on the screen. At this point, our page will be displayed on the screen.

    So the graphics layer is an important rendering vehicle and tool, but it doesn’t deal directly with the rendering layer, it deals with the composition layer.

  4. CompositingLayer

    Render layers that meet certain special conditions are automatically promoted to compositing layers by the browser. The compositing layer has a separate graphics layer, while other rendering layers that are not compositing layers share one with the first parent layer that has a graphics layer.

    So what special conditions does a rendering layer meet to be promoted to a compositing layer? Here are some common cases:

    • 3D transforms
    • video,canvas,iframe
    • opacityThe animation transformation
    • position: fixed
    • will-change
    • animationtransitionSet upopacity,transform,fliter,backdropfilter

View layers in Chrome

<html>
  <head>
    <title>Observation will change</title>
    <style>
      .box {
        /* will-change: transform, opacity; * /
        /* transform: translateZ(0); * /
        display: block;
        float: left;
        width: 40px;
        height: 40px;
        margin: 15px;
        padding: 10px;
        border: 1px solid rgb(136.136.136);
        background: pink;
        border-radius: 30px;
        transition: border-radius 1s ease-out;
        animation: Rotation 4s linear infinite;
      }
      @keyframes Rotation {
        0% {
          margin-left: 0px;
        }
        50% {
          margin-left: 30px;
        }
        100% {
          margin-left: 0px; }}body {
        font-family: Arial;
      }
    </style>
  </head>

  <body>
    <div id="controls">
      <button id="start">start</button>
      <button id="stop">stop</button>
    </div>
    <div>
      <div class="box">box</div>
      <div class="box">box</div>
      <div class="box">box</div>
      <div class="box">box</div>
    </div>
    <br />
    <script>
      let boxes = document.querySelectorAll(".box");
      let boxes1 = document.querySelectorAll(".box1");
      let start = document.getElementById("start");
      let stop = document.getElementById("stop");
      let stop_flag = false;

      start.addEventListener("click".function () {
        stop_flag = false;
        requestAnimationFrame(render);
      });

      stop.addEventListener("click".function () {
        stop_flag = true;
      });

      let rotate_ = 0;
      let opacity_ = 0;
      function render() {
        if (stop_flag) return 0;
        rotate_ = rotate_ + 6;
        if (opacity_ > 1) opacity_ = 0;
        opacity_ = opacity_ + 0.01;
        const command = "rotate(" + rotate_ + "deg)";
        for (let index = 0; index < boxes.length; index++) {
          boxes[index].style.transform = command;
          boxes[index].style.opacity = opacity_;
        }
        requestAnimationFrame(render);
      }
    </script>
  </body>
</html>

Copy the code

In the rendering mechanism above, we saw layers, and we can feel layer more intuitively in Chrome.

Same render layer

When we do not enable Transform, we see that the page has only one plane. So we only have one layer on this page.

So at this point, we only have one render layer for this page, and we need to redraw the entire page while the animation is running.

Create a new render layer

Now generate a separate layer for each box and turn on the transform: translateZ(0) comment above. When we look at Layers, we can see that each box is a separate layer.

In this case, when the animation is running, it just redraws each box rendering layer, which is often referred to as GPU acceleration

So what if we click on the start button and see?

We’ll see that the layer becomes a layer again, so transform:translateZ(0) does turn on a separate layer, which allows us to turn on GPU acceleration, but it collapses into a layer once the JS animation is added.

Explicit ascension

Moving forward, will-change: transform, opacity; With comments open, elevate the layer explicitly to a composite layer and see what it looks like

You can see that we now have js animation on, but the box layer has not collapsed either. Here we have made explicit promotion, so we have promoted it to a composite layer, which has its own graphics layer and no longer reuses the graphics layer of the parent layer.

Optimization in development

By default, browsers don’t do any layering, which means that all dom nodes are on one layer.

This means that the rendering granularity of our page is very large, and even a few small changes in this page will trigger the rearrangement and redrawing of the entire page, which will affect the rendering efficiency of the page.

We know that frameworks such as React and Vue update components at the component level, i.e. which component is updated, so only this component will be updated to improve rendering efficiency.

In the process of rendering updates, browsers also have the concept of “component-level update” like React and Vue, that is, layered rendering.

In other words, if you take a single dom node and assign it to a layer, it will be updated independently of the entire page, reducing rendering granularity and optimizing rendering.

For example, we used will-change above

Layered rendering

👇🏻 so we can just use the following code?

* {
  will-change: all;
}
Copy the code

Of course not! While layering allows for accelerated use of GPU rendering, it does not affect other layers. However, unchecked performance degrades.

  • When you have more layers, the more time it takes to compose layers, the smaller the area you draw when repainting, and the faster the updates.

  • When you have fewer layers, it takes less time to compose layers, the larger the area you draw when repainting, and the slower the update.