共计 2864 个字符,预计需要花费 8 分钟才能阅读完成。
长列表网页置信大多数开发者都遇到过,在 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 属性进去的工夫并不是太长,尽管它的欠缺,这一问题或者在未来也可能失去解决。