章
目
录
咱搞前端开发的都知道,用户体验那可是重中之重。在众多影响用户体验的因素里,页面性能的表现尤为关键。今天就跟大伙说说前端性能指标里的CLS,这可是个不能忽视的重要指标。
一、CLS到底是啥?
CLS(Cumulative Layout Shift)是Web Vitals(Web核心指标)里的一员,主要用来衡量页面加载时内容出现的布局偏移情况。打个比方,你在加载网页的时候,原本好好待在某个位置的按钮,突然“跑”到别的地方去了,或者图片加载时把周围的内容都“挤”开了,这些情况就是布局偏移。这种意外的布局变化会让用户觉得很困惑,体验感直线下降。所以说,CLS就是用来反映这种“意外布局变化”对用户影响程度的指标。
一个好的网站,CLS得分最好别超过0.1。为了保证大部分用户都能有不错的体验,通常会按照移动设备和桌面设备来分别统计,以网页加载时间的第75个百分位数作为衡量阈值。要是CLS值大于0.25,那可就有点糟糕啦,用户大概率会在浏览页面时遇到各种问题。
二、布局偏移的那些事儿
(一)布局偏移是怎么产生的?
布局偏移在页面加载或者用户交互过程中经常出现,主要是因为页面元素的布局突然发生了变化。这背后的“罪魁祸首”通常有下面这些。
- 异步加载的内容:像图片、广告、字体、视频这类资源,在加载之前,浏览器要是没给它们预留足够的空间,等这些资源加载完,页面其他内容就只能“挪位置”了。
- 动态内容插入:JavaScript在页面加载后往页面里动态插入内容,如果事先没规划好空间,页面布局肯定得变。
- 字体加载:网页用到的Web字体加载时,要是没提前预留空间,文字的大小、位置就可能会变,布局偏移也就跟着来了。
- 动画效果:给元素加动画,要是没控制好动画的时机,或者没处理好容器大小,就容易导致页面布局突变。
(二)布局偏移分数怎么算?
布局偏移分数,也叫布局偏移得分(Layout Shift Score),是用来衡量每次元素布局偏移的。计算这个分数要考虑两个因素:影响面积和偏移距离。公式是:布局偏移得分 = 影响区域面积的比例 × 偏移的距离。
影响区域面积指的是发生变化的元素占页面视口区域大小的百分比,占比越大,得分越高;偏移距离则是元素在屏幕上水平和垂直方向的位移,移得越远,得分也越高。比如说,一个按钮突然移动,影响了页面布局,那就会增加布局偏移数。
(三)撞击分数和距离分数
- 撞击分数:主要看页面元素的偏移有没有对用户交互产生负面影响。想象一下,你正要点一个按钮,结果按钮突然跑了,你点到了别的地方,这就很影响操作。撞击分数就是衡量这种干扰程度的,分数越高,对用户操作的干扰就越大。
- 距离分数:用来衡量布局偏移时,元素移动距离对布局变化的影响。它和元素的偏移距离、影响区域面积都有关系,计算公式是:距离分数 = 偏移的距离 × 影响区域的面积比例。偏移距离越大,影响区域面积越大,距离分数就越高,对用户体验的影响也就越明显。
三、不同类型的布局偏移
(一)用户发起vs意外布局偏移
不是所有的布局偏移都不好。像用户点击按钮、输入文字这些操作引起的布局变化,属于用户发起的布局偏移,一般来说是可以接受的。只要布局变化的时机和方式能让用户清楚感知到和自己操作的关系就行。不过,如果操作需要一些时间完成,比如发起网络请求,最好提前给加载的内容预留空间,再显示个加载指示器,不然用户可能会因为布局变化而操作失误。
还有,用户输入后500毫秒内发生的布局偏移,会被标记为hadRecentInput
,不会被当作意外布局变化。这是因为这种偏移和用户操作紧密相关,不会干扰到用户。
(二)动画和过渡效果
动画和过渡效果用得好,能大大提升用户体验,让页面内容的变化看起来更自然流畅。比如说,元素移动或改变时,用动画让它平滑过渡,用户就能清楚地知道发生了什么。要是元素突然偏移,用户就会很懵。
在实现动画的时候,用CSS的transform
属性是个不错的选择。比如改变元素大小用transform: scale()
,移动元素用transform: translate()
,这样可以避免触发布局偏移。要是直接修改height
、width
、top
、left
这些属性,可能会导致页面重新计算布局,引起不必要的布局偏移。
四、如何衡量CLS?
CLS是所有布局偏移得分的累积,计算公式是:CLS = ∑(每次布局偏移的得分)。假设页面上有两个元素发生了布局偏移,分别算出它们的布局偏移得分,再把这些得分加起来,就是CLS的值。
(一)在JavaScript中衡量布局偏移
在JavaScript里,一般用PerformanceObserver API来监听layoutshift
事件,再结合LayoutShift接口获取布局偏移的数据,从而计算布局偏移得分。下面这段代码展示了具体做法:
// 设置PerformanceObserver来监听layout-shift事件
const observer = new PerformanceObserver((entryList, observer) => {
let cls = 0; // 初始化累计布局偏移(CLS)
// 遍历所有的布局偏移事件
entryList.getEntries().forEach((entry) => {
// 获取布局偏移的影响区域比例
const impactArea = entry.value;
// 获取偏移的距离
const distance = entry.distance;
// 计算布局偏移得分
const shiftScore = impactArea * distance;
cls += shiftScore; // 累加到CLS得分
console.log(`布局偏移得分: ${shiftScore}`);
console.log(`累计CLS: ${cls}`);
});
});
// 启动PerformanceObserver来监听layout-shift事件
observer.observe({ type: "layout-shift", buffered: true });
(二)使用web-vitals库衡量CLS
用web-vitals
库来衡量CLS就更简单了。调用getCLS()
函数,它会自动监测并计算页面里所有的布局偏移,然后返回一个包含CLS值和其他相关信息的metric对象。通过监听这个返回的数据,开发者就能实时掌握页面的视觉稳定性,方便优化页面布局。代码示例如下:
import { getCLS } from "web-vitals";
getCLS((metric) => {
console.log("CLS:", metric.value);
});
这样就能在控制台输出页面的CLS值了,后续还能把这个数据发送到分析服务器,用来监控和优化页面性能。
五、CLS优化策略
想要优化CLS,提升页面的视觉稳定性,就得从多个方面入手,把可能导致布局偏移的因素都考虑到。
(一)动画和过渡效果优化
- 避免修改布局属性引起动画:用动画或过渡效果的时候,修改
height
、width
、top
、left
这些布局属性,很容易导致页面重排,引发布局偏移,影响CLS值。所以,推荐用transform
或opacity
来做动画。比如,平移元素用transform: translate()
,淡入淡出元素用opacity
属性。
/* 使用translate()移动元素 */
.element {
transform: translateX(100px); /* 水平平移100px */
}
.element {
opacity: 0;
transition: opacity 0.5s ease;
}
.element.visible {
opacity: 1;
}
- 合理控制动画时机和过渡效果:动画效果虽然好,但要是用得不对,也会影响页面稳定性。动画最好在用户明确交互之后触发,别在页面加载的时候突然冒出来。另外,还可以通过
prefers-reduced-motion
媒体查询,根据用户的设置来调整动画复杂度,甚至禁用某些动画。
@media (prefers-reduced-motion: reduce) {
.element {
transition: none; /* 禁用过渡效果 */
}
}
(二)为动态内容预留空间
- 图片和广告内容处理:图片和广告经常是CLS增加的“元凶”。为了避免这种情况,要给图片预设尺寸,不管是图片、视频还是广告元素,都设置好明确的
width
和height
,这样浏览器就能提前预留空间,防止加载时推移其他内容。
<img src="image.jpg" width="600" height="400" alt="Image description" />
对于还没加载的图片,也可以用占位符或者骨架屏来预留空间,让用户看到稳定的页面结构。
<div style="width: 600px; height: 400px; background: #e0e0e0;">
<!-- 图片加载前的占位符 -->
</div>
- 广告和嵌入内容优化:广告和嵌入式内容加载时也可能导致布局偏移。要给广告容器设置固定尺寸,提前预留好空间。还可以用异步加载的方式,通过
async
或defer
属性延迟广告加载时间,减少对页面其他内容的影响。
<div style="width: 300px; height: 250px;">
<!-- 广告内容 -->
</div>
(三)字体加载优化
自定义字体加载可能会让文本闪烁、跳动,增加CLS。使用font-display: swap
,可以让浏览器在自定义字体加载完成前先用备用字体,等字体加载好了再切换,这样就能减少因字体加载延迟引起的视觉问题。
@font-face {
font-family: "MyCustomFont";
src: url("myfont.woff2") format("woff2");
font-display: swap; /* 字体加载时使用备用字体 */
}
(四)避免大规模DOM操作
页面加载或者用户交互过程中,大量插入或删除DOM元素,会让页面重新计算布局,引发布局偏移,增加CLS。可以用懒加载、虚拟滚动来按需加载内容,或者采用分步加载的方式,先加载重要内容,再逐步加载其他内容,避免页面布局剧烈变化。
(五)使用现代布局方式
CSS Grid和Flexbox布局比传统的position
或float
布局更稳定,处理响应式布局也更出色,能有效减少因布局问题导致的偏移。开发的时候可以多用这两种布局方式。
.container {
display: flex;
flex-direction: column;
}
六、总结
CLS作为衡量页面视觉稳定性的关键指标,直接关系到用户体验。咱们在开发过程中,一定要重视CLS的优化,从各个可能导致布局偏移的细节入手,像为动态内容预留空间、避免触发布局重排、合理使用动画等,努力让CLS值保持在0.1以下,给用户提供更流畅、稳定的浏览体验。大伙要是对CLS还有啥疑问,或者有更好的优化经验,欢迎在评论区留言讨论!