As most developers have encountered with long-list web pages, browser rendering can be very slow with too many DOM elements, which can affect the user experience. As a result, we often optimize using different methods such as virtual scrolling, paging, and pull-up loading. The idea is the same, rendering only the visible area and loading more content when the user needs it. Either way, you need to write a lot of JS or CSS logic to achieve it.

Now, we have one more way — Content-visibility. Only need one line of CSS code, you can achieve visible web page only load visible area content, so that the rendering performance of the web page has been several times improved!

introduce

Content-visibility is a CSS property that controls whether an element presents its content, allowing users to potentially control the presentation of the element. Users can use it to skip the rendering of elements (including layout and drawing) until they need to, greatly improving the initial rendering of the page.

value

The content-visibility attribute has three optional values:

  • Visible: the default value. There is no impact on layout or rendering.
  • Hidden: The element skips the rendering of its content. User agent functions (for example, find in a page, Tab to navigate sequentially, etc.) do not access skipped content, nor can they select or focus. Similar to setting the display: None property on its contents.
  • Auto: For elements in the user’s visible area, the browser renders their contents normally. For elements that are not visible, the browser temporarily skips rendering of their content until they are visible to the user.

Effect of contrast

Before using

code

Simply use 100 cards in a browser and animate them with a sweep effect:

<html>
  <head>
    <title>content-visibility</title>
    <style type="text/css">
      .card {
        position: relative;
        overflow: hidden;
        transition-duration: 0.3 s;
        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>
    <! -... -->
    <! <div class="card"></div>
    <! -... -->
    <div class="card"></div>
  </body>
</html>
Copy the code

rendering

As you can see from Chrome, the rendering time took 1454ms:

After using

code

Class add content-visibility: auto to card; :

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

rendering

You can clearly see that using content-visibility: auto; The post-render time is only 381ms, a nearly 4-fold improvement in performance! And as element content gets more complex, improved performance increases more dramatically.

As can be seen from the dom structure changes below, when card is not in the visible area of the screen, its content (::before, etc.) will appear when the element is visible:

defects

compatibility

Content-visibility is a new feature for chrome85 this year, so compatibility isn’t high yet, but it will be resolved in the near future. The current compatibility is as follows:

Some elements cause browser rendering problems

The problem

When part of the content of an element, such as the tag, the height of the element is determined by the image content, so in this case, if you use content-visibility, the IMG outside the visible view is initially unrendered and has a height of 0. As the scroll bar slides down, the page height increases, causing scrolling problems.

The following code:

<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, & FM = 26 & gp = 0. 784420394 JPG"
        alt="The dog"
      />
      <! -... -->
      <! -->
      <! -... -->
      <img
        src="Https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=1057266467, & FM = 26 & gp = 0. 784420394 JPG"
        alt="The dog"
      />
    </div>
  </body>
</html>
Copy the code

It looks like this, and you can see that the scroll bar has problems as the image is rendered:

solution

Contains -intrinsic-size: 312px; contains-intrinsic-size: 312px; contains-intrinsic-size: 312px; This appends the content to an initial height value. (If the height is not fixed, you can also attach a rough initial height value, which will reduce the scrollbar problem relatively).

Modify the code as follows:

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

If you look at the scroll bar again, there is no problem:

conclusion

Content-visibility is a useful CSS property that can be used to optimize long lists by using a single line of CSS instead of virtual scrolling, pull-up loading, and more.

Although compatibility is not very good right now, it will not be a problem in the near future. Contain intrinsically -size if your list items are the same height, set them to contain- intrinsically -size. This property is not recommended if the list item height is not fixed and the user’s scrollbar experience is very important. Of course, this CSS property hasn’t been around for a long time, but as it improves, the problem may be solved in the future.