Just one line of CSS code can improve the rendering performance of long list web pages by more than several times!

I believe most developers have encountered long list web pages. When there are too many DOM elements, the browser rendering will be very slow, which will greatly affect the user experience.

Therefore, we often use different methods such as virtual scrolling, paging and pull-up to optimize. The idea of these methods is the same. They only render the visible area and load more content when users need it. No matter which of the above methods, you need to write a lot of js or css logic to implement.

Now, we have another way - content visibility. Only one line of CSS code is needed to load only the content of the visible area of the visible web page, so that the rendering performance of the web page can be improved several times!

introduce

Content visibility is a css attribute that controls whether an element renders its content, allowing users to potentially control the rendering of elements. Users can use it to skip the rendering of elements (including layout and drawing) until they need it, which greatly improves the initial rendering of the page.

value

The content visibility attribute has three optional values:

  • visible: default value. It has no impact on layout and rendering.
  • hidden: element skips rendering of its content. User agent functions (for example, find in the page, navigate in Tab order, etc.) do not access skipped content, nor can they select or focus. It is similar to setting the display: none attribute on its content.
  • auto: for elements in the user's visible area, the browser will render their contents normally; For elements in the invisible area, the browser will temporarily skip the rendering of their contents, and when they are in the user's visible area, the browser will render their contents.

Effect comparison

Before use

code

Use the following code to simply use 100 cards in the browser and animate the sweeping effect:

<html>
  <head>
    <title>content-visibility</title>
    <style type="text/css">
      .card {
        position: relative;
        overflow: hidden;
        transition-duration: 0.3s;
        margin-bottom: 10px;
        width: 200px;
        height: 100px;
        background-color: #ffaa00;
      }
      .card:before {
        content: '';
        position: absolute;
        left: -665px;
        top: -460px;
        width: 300px;
        height: 15px;
        background-color: rgba(255, 255, 255, 0.5);
        transform: rotate(-45deg);
        animation: searchLights 2s ease-in 0s infinite;
      }
      @keyframes searchLights {
        0% {
        }
        75% {
          left: -100px;
          top: 0;
        }
        100% {
          left: 120px;
          top: 100px;
        }
      }
    </style>
  </head>
  <body>
    <div class="card"></div>
    <div class="card"></div>
    <!-- ... -->
    <!-- 97 are omitted here<div class="card"></div> -->
    <!-- ... -->
    <div class="card"></div>
  </body>
</html>

Rendering effect

As can be seen from chrome, the rendering time took 1454ms:

After use

code

Add content visibility: Auto; to class card:

 .card {
    position: relative;
    overflow: hidden;
    transition-duration: 0.3s;
    margin-bottom: 10px;
    width: 200px;
    height: 100px;
    background-color: #ffaa00;
    content-visibility: auto;
  }
  .card:before {
    content: '';
    // ...

Rendering effect

It is obvious that content visibility: Auto; The post rendering time is only 381ms, and the performance is improved by nearly 4 times! Moreover, as the element content becomes more complex, the improved performance will increase more significantly.

It can also be seen from the dom structure change in the figure below that when the card does not appear in the visible area of the screen, its content (:: before and other animations) appears only when the element appears in the visible effect:

defect

compatibility

Content visibility is a new feature of chrome 85 this year, so the compatibility is not high at present, but I believe the compatibility problem will be solved in the near future. The current compatibility is as follows:

Some elements cause browser rendering problems

problem

When part of the content of an element, such as < img / > tags, the height of the element is determined by the image content. Therefore, in this case, if content visibility is used, the IMG outside the visible view is not rendered initially, and the height is 0. As the scroll bar slides down, the page height increases, which will cause problems in the scrolling of the scroll bar.

<html>
  <head>
    <title>content-visibility</title>
    <style type="text/css">
      .card {
        margin-bottom: 10px;
        content-visibility: auto;
      }
    </style>
  </head>
  <body>
    <div class="card">
      <img
        src="https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=1057266467,784420394&fm=26&gp=0.jpg"
        alt="puppy"
      />
      <!-- ... -->
      <!-- Omitted here n individual card content -->
      <!-- ... -->
      <img
        src="https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=1057266467,784420394&fm=26&gp=0.jpg"
        alt="puppy"
      />
    </div>
  </body>
</html>

The effect is as follows. It can be seen that the scroll bar will have problems with the presentation of the picture:

Solution ideas

To solve this problem, if the element height is known, you can use the contains intrinsic size attribute to add: contains intrinsic size: 312px; to the above card;, This will attach an initial height value to the content. (if the height is not fixed, you can also attach an approximate initial height value, which will reduce the problem of scroll bar relatively).

The modification code is as follows:

    <style type="text/css">
      .card {
        margin-bottom: 10px;
        content-visibility: auto;
        contain-intrinsic-size: 312px; // Add this row
      }
    </style>

Look at the scroll bar again and there will be no problem:

summary

Content visibility is a very practical CSS attribute. One line of CSS can replace many long list rendering optimization methods, such as virtual scrolling, pull-up loading and more.

Although its compatibility is not very good now, I believe it will not be a problem in the near future. Now let's look at the impact on the browser's scroll bar in some scenarios. If your list items have the same height, you can set an initial height through the contain intrinsic size. This property is not recommended if the list item is highly variable and attaches great importance to the user's scroll bar experience. Of course, this css attribute has not come out for a long time. Although it is perfect, this problem may be solved in the future.

Author: Lixiang https://juejin.cn/post/6908521872577527822

Posted by pck76 on Tue, 16 Nov 2021 19:45:45 -0800