您是否曾经在页面上突然发生变化时在线阅读文章?在没有警告的情况下,文字移动了,并且您失去了位置。甚至更糟:您将要点击一个链接或一个按钮,但是在手指落下的瞬间(BOOM),链接移动了,您最终单击了其他东西!
在大多数情况下,这种经历很烦人,但在某些情况下,它们会造成真正的损失。
页面内容的意外移动通常是由于异步加载资源或DOM元素动态添加到现有内容上方的页面而发生的。罪魁祸首可能是尺寸未知的图像或视频,呈现比其后备更大或更小的字体,或者是动态调整自身大小的第三方广告或小部件。
使这个问题变得更加棘手的是,网站在开发中的功能通常与用户的体验有很大不同。个性化或第三方内容在开发中的行为通常与在生产中的行为不同,测试图像通常已经在开发人员的浏览器缓存中,并且本地运行的API调用通常是如此之快,以至于延迟不明显。
累积版式移位(CLS)度量标准可以通过测量实际用户发生的频率来帮助您解决此问题。
什么是CLS?
CLS会测量在页面的整个生命周期中发生的每个 意外的版式移位的所有单独版式移位分数的总和。
甲布局移发生的任何时间的可见元素改变其从一个所再现的帧到下一个位置。(有关如何计算各个版式移位得分的详细信息,请参见下文。)
良好的CLS分数是多少?
为了提供良好的用户体验,网站应努力使CLS分数小于0.1。为了确保您达到大多数用户的这一目标,衡量移动设备和台式机设备的页面加载量的第75个百分位是一个很好的衡量标准。
要了解有关此建议背后的研究和方法的更多信息,请参阅:定义核心Web Vitals指标阈值
什么是位移?
布局移动由Layout Instability API定义,该APIlayout-shift
在视口中可见的元素在两帧之间更改其开始位置(例如,默认书写模式下的顶部和左侧位置)时,都会报告条目。这些元素被认为是不稳定元素。
请注意,仅当现有元素更改其起始位置时,才会发生布局转换。如果将新元素添加到DOM或现有元素更改了大小,则只要更改不会导致其他可见元素更改其起始位置,该元素就不会算作布局偏移。
如何计算CLS分数
要计算布局平移分数,浏览器将查看视口大小以及两个渲染帧之间视口中不稳定元素的移动。布局偏移分数是该运动的两个度量的乘积:影响比例(impact fraction) 和 位移比例(均在下面定义)。
layout shift score = impact fraction * distance fraction
影响比例
前一帧 和当前帧的所有不稳定元素的可见区域的并集(占视口总面积的一部分)是当前帧的影响分数。
在上图中,有一个元素在一帧中占据了视口的一半。然后,在下一帧中,元素下移视口高度的25%。红色的虚线矩形表示两个帧中元素的可见区域的并集,在这种情况下,其为总视口的75%,因此其 影响分数为0.75
。
位移比例
布局移位分数方程的另一部分测量不稳定元素相对于视口移动的距离。的距离分数 是最大的距离的任何不稳定的元件在帧已经移动(水平或垂直任一)通过视域的最大尺寸(宽度或高度,取较大值)分开。
上面的示例中,最大视口尺寸是高度,不稳定元素已移动了视口高度的25%,这使得 距离分数为0.25。
因此,在此示例中,碰撞分数为0.75
,距离分数 为0.25
,因此版式位移分数为0.75 * 0.25 = 0.1875
。
下一个示例说明将内容添加到现有元素如何影响布局平移分数:
在此示例中,灰色框会更改大小,但其开始位置不会更改,因此它不是不稳定的元素。
“click me” 按钮以前不在DOM中,因此它的开始位置也不会更改。
但是,绿色框的开始位置确实会发生变化,但是由于已将其部分移出视口,因此在计算碰撞率时不会考虑不可见区域。两个框架中绿色框的可见区域的并集(用红色虚线矩形表示)与第一帧中绿色框的区域相同-视口的50%。该影响分数是0.5
。
的距离分数被示为具有紫色箭头。绿色框已向下移动了约14%的视口,因此距离分数为0.14
。
布局移位分数是0.5 x 0.14 = 0.07
。
最后一个示例说明了多个不稳定元素:
上面的第一帧中,对动物的API请求有四个结果,按字母顺序排序。在第二帧中,更多结果将添加到排序列表中。
列表中的第一项(“猫”)在各帧之间不会更改其开始位置,因此很稳定。同样,添加到列表中的新项目以前不在DOM中,因此它们的开始位置也不会更改。但是标有“ Dog”,“ Horse”和“ Zebra”的项目会移动其起始位置,从而使它们成为不稳定的元素。
同样,红色,点缀矩形表示这三者的联合不稳定因素前,后区“,在这种情况下是视域的面积(约38%的影响分数的0.38
)。
箭头表示不稳定元素从其起始位置开始移动的距离。蓝色箭头表示的“斑马”元素移动最多,移动了视口高度的30%。这就是本例中的 距离分数0.3
。
布局移位分数是0.38 x 0.3 = 0.1172
。
预期与意外布局的变化
并非所有的布局转换都不好。实际上,许多动态Web应用程序经常更改页面上元素的开始位置。
用户启动布局的变化
仅当用户不期望布局转换时,它才是糟糕的。另一方面,响应于用户交互(单击链接,按下按钮,在搜索框中键入内容等)而发生的布局偏移通常很好,只要该偏移发生在与交互关系足够近的位置即可向用户清除。
例如,如果用户交互触发了可能需要一段时间才能完成的网络请求,则最好立即创建一些空间并显示一个加载指示器,以避免在请求完成时出现不愉快的布局变化。如果用户没有意识到正在加载某些东西,或者对资源何时准备就绪一无所知,他们可能会在等待时尝试单击其他内容,而某些内容可能会从它们下面移出。
在用户输入的500毫秒内发生的布局转换将hadRecentInput
设置该 标志,因此可以将其从计算中排除。
动画和过渡
动画和过渡效果很好,是一种在不引起用户惊讶的情况下更新页面内容的好方法。在页面上突然发生意外变化的内容几乎总是会产生不良的用户体验。但是,内容逐渐自然地从一个位置移动到另一个位置通常可以帮助用户更好地了解发生了什么,并在状态更改之间进行指导。
CSStransform
属性使您可以为元素设置动画,而不会触发布局转换:
- 而不是更改
height
和width
属性,请使用transform: scale()
。 - 左右移动的元件,避免改变
top
,right
,bottom
,或left
属性,并使用transform: translate()
来代替。
如何衡量CLS
现场的工具
实验室工具
在JavaScript中测量CLS
参考打造企业级私有前端监控体系课程中有介绍
示例:
const entryType = 'layout-shift' constobserver=newPerformanceObserver((list) => { list.getEntries().forEach(console.log); }) observer.observe({ entryTypes: [entryType] });
如何改善CLS
对于大多数网站,您可以遵循一些指导原则来避免所有意外的布局变化:
- 请务必在图片和视频元素上包含size属性,否则请使用CSS长宽比框之类的东西保留所需的空间。这种方法可确保在加载图像时浏览器可以在文档中分配正确的空间量。请注意,您还可以使用unsize-media功能部件策略 在支持功能部件策略的浏览器中强制执行此行为。
- 除非响应用户交互,否则切勿在现有内容上方插入内容。这样可以确保可以预期发生任何版式移位。
- 与将动画触发布局更改的属性动画相比,更喜欢使用转换动画。对过渡进行动画处理,以提供状态与状态之间的上下文和连续性。
有关如何改善CLS的深入探讨,请参见优化CLS。