乐趣区

关于前端:看如何用CSS代码让你的列表网页提升渲染性能

长列表网页置信大多数开发者都遇到过,在 DOM 元素过多的状况下,浏览器渲染会很慢,十分影响用户体验前端培训。
因而咱们会常常采纳虚构滚动、分页、上拉加载更多等不同的形式来进行优化,这些形式的思维都是一样的,都是只渲染可见区域,等用户须要时再加载更多的内容。而以上的形式无论哪种,都须要写大量的 js 或者 css 逻辑去实现。
而当初,咱们多了一种形式——content-visibility。只须要一行 CSS 代码,就能够实现可见网页只加载可见区域内容,使网页的渲染性能失去数倍的晋升!
介绍
content-visibility 是一个 css 属性,它管制一个元素是否出现其内容,能让用户潜在地管制元素的出现。用户能够应用它跳过元素的出现(包含布局和绘制),直到用户须要为止,让页面的初始渲染失去极大的晋升。
value
content-visibility 属性有三个可选值:
• visible: 默认值。对布局和出现不会产生什么影响。
• hidden: 元素跳过其内容的出现。用户代理性能(例如,在页面中查找,按 Tab 键程序导航等)不可拜访已跳过的内容,也不能抉择或聚焦。相似于对其内容设置了 display: none 属性。
• auto: 对于用户可见区域的元素,浏览器会失常渲染其内容;对于不可见区域的元素,浏览器会临时跳过其内容的出现,等到其处于用户可见区域时,浏览器在渲染其内容。

成果比照
应用前
代码
如下代码,在浏览器中简略的应用 100 个卡片,并对其设置扫光成果动画:
<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 个 <div class="card"></div> -->
<!-- ... -->
<div class="card"></div>

</body>
</html>
渲染成果
从 chrome 能够看出,渲染工夫破费了 1454ms:

应用后
代码
在 class 为 card 中增加 content-visibility: auto;:
.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: '';
// ...

渲染成果
能够显著的看到,应用 content-visibility: auto; 后渲染工夫只须要 381ms,性能晋升了近 4 倍!而且随着元素内容变简单,晋升的性能会有更显著的回升。

再从下图的 dom 构造变动中也能够看到,当 card 未呈现在屏幕可见区域内是,其内容 (::before 等动画) 在元素呈现在可见成果时才呈现:

缺点
兼容性
content-visibility 是 chrome85 往年新增的个性,所以目前兼容性还不高,然而置信兼容性的问题在不久的未来会失去解决。目前兼容性如下:

局部元素导致浏览器渲染出问题
问题
当元素的局部内容如 <img /> 标签这种,元素的高度是有图片内容决定的,因而在这种状况下,如果应用 content-visibility,则可见视图外的 img 初始未渲染,高度为 0,随着滚动条向下滑动,页面高度减少,会导致滚动条的滚动有问题。
<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="小狗"
  />
  <!-- ... -->
  <!-- 此处省略 n 个 card 内容 -->
  <!-- ... -->
  <img
    src="https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=1057266467,784420394&fm=26&gp=0.jpg"
    alt="小狗"
  />
</div>

</body>
</html>

解决思路
解决此问题,如果在已知元素高度的状况下,能够应用 contains-intrinsic-size 属性,为下面的 card 增加:contains-intrinsic-size:312px;,这会给内容附一个初始高度值。(如果高度不固定也能够附一个大抵的初始高度值,会使滚动条问题绝对缩小)。
批改代码如下:

<style type="text/css">
  .card {
    margin-bottom: 10px;
    content-visibility: auto;
    contain-intrinsic-size: 312px; // 增加此行
  }
</style>

再次看滚动条就没有问题了:

总结
content-visibility 是一个十分实用的 CSS 属性,通过一行 CSS 能够代替虚构滚动、上拉加载更多等多种长列表渲染优化形式。
尽管其兼容性当初不是很好,然而置信不久的未来这并不是问题。当初来看是局部场景下它对浏览器的滚动条影响问题,如果你的列表项高度雷同,那么能够通过 contain-intrinsic-size 来设置一个初始高度解决。如果列表项高度不固定而又非常重视用户的滚动条体验,那么不倡议应用此属性。当然了,这一 css 属性进去的工夫并不是太长,尽管它的欠缺,这一问题或者在未来也可能失去解决。

退出移动版