❝财富是对认知的补偿,不是对勤劳的奖励❞
大家好,我是「柒八九」。
今天我们来聊聊另外一个比较重要的性能指标CLS
。
如果想了解该系列文章(「浏览器底层原理&优化方案」),可以参考我们已经发布的文章。如下是往期文章。
CLS
是个啥CLS
的原理CLS
CLS
得分❞好了,天不早了,干点正事哇。
❝核心 Web 指标(
Core Web Vitals
)是一组用于评估网页性能的关键指标。 ❞
它由Google
提出,并成为Google排名算法的重要因素。核心 Web 指标
旨在衡量用户体验的关键方面,涵盖了加载速度
、交互性
和视觉稳定性
。
核心 Web 指标包括以下三个指标:
LCP
应在页面首次开始加载后的2.5 秒内发生。为了确保我们能够在大部分用户的访问期间达成建议目标值,对于上述每项指标,「一个良好的测量阈值为页面加载的第 75 个百分位数」,且该阈值同时适用于移动和桌面设备。
如果一个页面满足上述全部三项指标建议目标值的第 75 个百分位数,那么评核心 Web 指标
合规性的工具应评判该页面为通过。
图片的宽高比在渲染时起到重要作用,它影响了图片在页面中的布局和显示效果。以下是宽高比在渲染中的几个方面作用:
宽高比
来确定图片在文档流中的尺寸和位置。宽高比可以帮助浏览器确定图片的宽度和高度,以便正确地分配空间。宽高比
决定了图片在显示时的比例和形状。如果图片的宽高比与显示容器(如<img>
标签或CSS容器)的宽高比不匹配,图片可能会被拉伸或压缩,导致失真或变形。宽高比
可以确保图片在不同屏幕尺寸和设备上呈现出良好的外观。通过设置宽高比,可以让图片自适应容器的尺寸变化,并保持正确的比例。❝总而言之,
宽高比
在图片的布局、显示和响应式设计方面都起到重要作用,它能够确保图片在不同环境下呈现出正确的比例和外观,并避免布局偏移的问题。 ❞
确定或设置一个图片的宽高比可以通过以下几种方法实现:
padding-top
属性,将上边距设置为以百分比表示的宽高比。16:9
,可以将padding-top
设置为56.25%(9除以16乘以100)。margin
和padding
属性的「垂直方向的百分比值都是相对于宽度计算」的,这个和top, bottom等属性的百分比值不一样。.image-container {
position: relative;
width: 100%;
padding-top: 56.25%; /* 16:9 宽高比 */
}
.image-container img {
position: absolute;
width: 100%;
height: 100%;
object-fit: cover;
}
naturalWidth
和naturalHeight
属性,然后进行相应的计算得出宽高比。const img = document.querySelector('img');
const aspectRatio = img.naturalWidth / img.naturalHeight;
确定宽高比后,我们可以将其应用于图片容器或使用相应的CSS样式将其应用于图片本身,以确保在渲染和布局过程中正确显示图片的宽高比。
FOIT
/FOUT
FOIT
和FOUT
是与Web字体加载相关的术语。
❝
FOIT
代表"Flash of Invisible Text"
,意为「不可见文本的闪烁」。 ❞
当使用Web字体时,浏览器在下载字体文件时,会显示一段时间的空白文本,直到字体文件完全加载完成。这段时间内,用户可能会看到页面上出现了空白文本,然后突然闪现出字体样式。这种体验被称为FOIT
。
❝
FOUT
代表"Flash of Unstyled Text"
,意为「未样式化文本的闪烁」。 ❞
与FOIT类似,当使用Web字体时,浏览器可能会先显示系统默认字体,然后在字体文件加载完成后,突然将文本样式化为所需的Web字体。这种体验被称为FOUT
。
FOIT
和FOU
T都是由于Web字体加载的延迟而导致的不佳用户体验。用户可能会看到文本内容在加载过程中发生闪烁或样式变化,给页面的整体稳定性和一致性带来了困扰。为了解决FOIT和FOUT问题,可以使用CSS属性,如font-display
,来控制字体加载和显示的方式,以平滑地呈现文本内容,提高用户体验。
想象一下:你正在加载一个网站,它看起来准备就绪。你点击一个博客的图片来阅读文章,突然整个页面发生了变化,因为其他内容刚刚加载完毕。你点击了完全不相关的东西,加载了一个你根本没有打算打开的页面。如果你自己经历过这个问题,你就知道累积布局位移
(Cumulative Layout Shift,CLS)对网站的用户体验
造成了多大的负面影响。
❝
CLS
:是Cumulative Layout Shift
的简写,中文名称累积布局位移
。 衡量网页「视觉稳定性」的网络性能指标 ❞
以下是一个网站的布局,在页面加载过程中不断变化。在下面的动图中,我们的视口保持不变,也没发生页面滚动,但页面自行发生了巨大的位移。
作为访问该网站的用户,我们可能「无法确定页面何时完成加载」。我们可能会尝试点击一个新闻故事,结果页面布局发生了巨大变化。这样一来,我们就会进入错误的页面,不得不浪费时间返回。根据页面的不同,这种情况可能会发生多次。如果频繁发生这种情况,我们就会失去对该页面继续访问的兴趣,导致用户留存度「断崖式」下降。
同时,CLS
分数「可能会影响我们从谷歌和其他搜索引擎获得的流量」。
网站越复杂,其CLS
得分就越高的可能性越大(只是可能性比较大,复杂的网站我们也可以通过优化将CLS
控制在合理的范围内)。例如,像谷歌首页这样的简单布局就没有CLS,因为它们只包含很少的元素:
❝
布局偏移
发生是因为浏览器倾向于「异步加载页面元素」。更重要的是,页面上可能有具有未知尺寸
的媒体元素。这种组合意味着在加载完成之前,浏览器无法确定各个元素将占用多少空间。因此产生了剧烈的布局位移。 ❞
CLS
有趣的地方在于它可以通过各种工具进行客观测量,但也是以用户为中心的,因为每个用户的设备
可能会影响我们网站的布局如何发生位移。虽然我们无法控制这一方面,但我们肯定可以采取预防措施,以使其影响最小化。
❝
CLS
是Google用来评估网站提供强大用户体验
的三个核心网络指标[1]之一。 之前,我们已经在浏览器之性能指标-LCP介绍过LCP
。有兴趣的可以参考之前的文章。 ❞
❝
CLS
分数受「没有在页面上指定空间」的每个内容的影响,导致它们意外加载并移动其他内容,从而导致页面抖动。 ❞
根据谷歌文档[2]的说法,CLS 较差的最常见原因为:
FOIT
)/无样式文本闪烁 (FOUT
) 的网络字体CLS
的分数越低,布局就越稳定。谷歌性能测量工具使用的官方CLS阈值如下:
为了达到“良好”
的CLS阈值,谷歌建议在所有页面浏览中,将CLS分数保持在0.1以下的比例达到75%。
CLS通过比较两个渲染帧来计算页面元素的移动程度
和布局变化对视口的影响部分。
❝CLS有两个因素:影响分数(Impact Fraction)和距离分数(Distance fraction)。 ❞
❝要计算
影响分数
,首先需要计算影响区域
。 ❞
影响区域(Impact Region)定义了布局偏移所影响的区域。谷歌会将原始帧
与布局偏移后的帧进行比较,并识别出所有受影响的页面元素,从而定义了影响区域。
影响区域通常是一个矩形,但如果存在多个布局偏移,无论是水平还是垂直的,它可能是一个更复杂的形状。
要定义影响分数
(Impact Fraction),需要将影响区域
的面积除以视口的面积:
❝影响区域的面积 / 视口的面积 = 影响分数 ❞
首先,我们需要计算移动距离
。
移动距离定义了「布局偏移前后给定元素的位置之间的距离」。它基本上回答了一个问题:「元素移动了多远」?
一旦计算出移动距离,就可以通过将最大移动距离
除以视口的高度
来计算距离分数:
❝最大移动距离 / 视口高度 = 距离分数 ❞
接下来是计算布局偏移分数
。我们需要将影响分数
乘以距离分数
,以获得单个动画帧的布局偏移分数:
❝影响分数 × 距离分数 = 单个动画帧的布局偏移分数 ❞
谷歌在会话窗口中对布局偏移进行分组的处理。
❝会话窗口实际上是我们的页面生命周期内的时间段,在其中对布局偏移进行汇总。 ❞
当页面发生布局偏移时,会打开一个会话窗口。「该窗口最长可以持续5秒」,但如果「在初始偏移后的1秒内没有连续的布局偏移发生,窗口会提前关闭」。
布局偏移然后在会话窗口内进行汇总。给定页面的「最终CLS分数是具有最大总分数的会话窗口的分数」 - 其他会话窗口不会影响我们的CLS。
举个例子:
第三个布局偏移发生在2秒后(此时,第三个布局偏移和前两个被分在两个不同的会话窗口中),因此它属于一个单独的会话窗口。前一个会话窗口在第二个布局偏移后的1秒后关闭。
因此,在这种情况下,页面的最终CLS分数将为0.1 + 0.2 = 0.3
(0.3
>0.25
)!第三个布局偏移不影响最终分数。
❝CLS会忽略在用户输入后的0.5秒内出现的所有布局偏移。这被称为
输入排除窗口
(input exclusion window)。这意味着在用户与网站进行交互后的500毫秒内,CLS测量会停止。 ❞
由于CLS可以在实验室环境
和真实用户交互
中进行测量,我们可以得到CLS实验室分数
和CLS实际用户数据
的两种数据。
❝
实验室数据
意味着使用工具来模拟用户的体验。 ❞
这就像实验室测试一样,几乎是真实的,但在受控环境中进行,结果只涵盖了一小部分可能的情况。
我们可以通过以下性能工具访问我们的CLS实验室数据:
真实用户数据
是基于真实用户交互的数据。由谷歌和其他第三方收集,它可以让我们看到更全面的情况。我们可以将真实用户数据与实验室结果进行比较。对于谷歌来说,真实用户数据的主要来源是Chrome User Experience Report
,也称为CrUX
。
通过以下方式可以访问CrUX
数据:
我们从上面挑选一个功能完备并且操作简单的工具 - PageSpeed Insights[12]
它与Google的核心 Web 指标
直接相关,因此我们可以直接看到我们的CLS得分如何影响Google对我们的网站的评估。
该服务允许我们输入一个URL,并根据Google过去28天收集的数据为其提供综合性能评分。该评分考虑了多个指标,包括CLS、FCP和LCP。
在这个测试中,我们选择了一个没有明显CLS的网站。PageSpeed Insights证实了我们的猜想,它返回了极其积极的结果,并显示出较高的CLS得分。
请注意,PageSpeed Insights为每个得分提供了百分比的细分。在这种情况下,91%的用户在加载测试网站时没有经历过布局位移。然而,剩下的访问者确实经历了某种程度的布局位移。
这在CLS和其他核心 Web 指标
方面是可以预料的。用户体验会根据他们使用的设备、网络连接和许多其他因素而大大不同。几乎没有办法确保用户永远不会遇到CLS,但我们可以采取预防措施来优化它,使该百分比尽可能低。
除了现场数据外,PageSpeed Insights还提供了所谓的实验室数据
。
❝
实验室数据
是基于单次测试的性能评分,而不是基于长时间收集的数据(被视为现场数据)。 ❞
在我们的测试中,我们获得了一个CLS得分为零,这意味着没有布局位移。针对这一特定测试而言是如此。现在让我们将其与另一个得分没有那么高的网站进行比较。
为了符合Google的标准,我们的CLS得分应该低于0.10。超过这个值意味着布局发生了显著且明显的位移,这会导致用户体验较差。
如果我们想确定网站上哪些元素导致了布局位移,可以使用Chrome开发者工具进行调查。如果我们打开开发者工具(CTRL-SHIFT-I
)并切换到"Performance"
选项卡,我们可以在浏览网页时记录性能测试。
在停止录制后,Chrome开发者工具会返回一个时间轴,显示加载时间、各个请求和核心网络指标。从这个时间轴中,我们可以选择Layout Shifts
下列出的各个布局位移事件。通过这种方式,我们可以看到它们对应的元素是什么。
一旦我们知道哪些元素导致了布局位移,我们可以采取措施来解决这个问题。
与其事后捶胸顿足
,不如防范于未然
。
通过懒加载,我们可以优化页面的加载并减少启动时的负担。然而,主要图片可能不适合懒加载,特别是如果它在视窗顶部明显显示,因为这种技术可能不是这些元素的最佳解决方案。
动画可能导致布局偏移,但并非所有动画都会计入CLS分数。chrome
忽略CSS变换(transform)的变化 - 因此,如果我们的动画使用CSS的变换属性,它不会影响我们的CLS。
内容分发网络(CDN)是一组地理分布的服务器,可以缓存内容并协同工作以减少响应用户请求所需的时间。服务器响应时间过慢可能导致布局偏移,因此对某些资源使用CDN可能有助于防止页面上的高CLS。
硬编码页眉和菜单元素可以导致页面布局更一致和稳定,因为页眉和菜单的位置和外观始终保持相同。
如果我们的网站使用外部托管的字体,它们可能是FOIT
(闪烁的不可见文本)和FOUT
(闪烁的未样式化文本)的主要原因。
为了避免这种情况,我们可以使用font-display
值,例如auto
、swap
、block
、fallback
和optional
。
font-display: swap;
:这将在字体加载完成之前显示备用字体,然后在字体加载完成后再切换为所需的字体。@font-face {
font-family: 'MyWebFont';
src: url('webfont.woff2') format('woff2'),
url('webfont.woff') format('woff');
font-display: swap;
}
font-display: fallback;
:这将在字体加载完成之前显示备用字体,然后在字体加载完成后应用所需的字体样式,但可能会导致文本布局变化。@font-face {
font-family: 'MyWebFont';
src: url('webfont.woff2') format('woff2'),
url('webfont.woff') format('woff');
font-display: fallback;
}
font-display: optional;
:这允许浏览器自行决定是否加载和显示字体,可以提高页面加载性能,但可能会导致字体样式稍后应用。@font-face {
font-family: 'MyWebFont';
src: url('webfont.woff2') format('woff2'),
url('webfont.woff') format('woff');
font-display: optional;
}
为了获得更好的效果,我们还可以使用<link rel=preload>
预加载字体文件 - 这样,它们将作为优先下载的资源。
就网站性能而言,「最好使用已经具有精确尺寸的图像」。这样,浏览器就不需要在适当地调整大小上花费时间。然而,当无法提供精确尺寸的图像时,我们应为显示的每个图像设置宽度和高度属性。这样,用户的浏览器将准确知道图像的位置,而不需要在最后一刻调整布局。
在互联网的早期,网页开发人员通常在网站的各个地方都包括width
和height
属性。它看起来像这样:
<img src="example.jpg" width="800" height="300" alt="示例图像">
随着响应式网页设计的兴起,这种做法变得不那么流行。由于这种新的方法,开发人员开始使用CSS来调整图像的大小。
使用这种方法,只有在浏览器开始下载图像后才会分配空间。在所有图像都显示后,布局会发生变化,导致不必要的偏移。
调整图像大小的更好方法是使用宽高比
(aspect ratio)。它是宽度与高度的比例(例如16:9)。
使用宽高比
可以让浏览器计算显示图像所需的空间 - 从而减少布局偏移的风险。
srcset
属性如果我们要处理响应式图像,可以使用srcset
属性。它允许我们设置多个图片尺寸,并让浏览器显示最合适的尺寸。
当处理响应式图像时,可以使用srcset
属性来指定不同大小和分辨率的图像源,让浏览器根据需要选择最合适的图像进行加载和显示。以下是srcset
属性的用法示例代码:
<img src="image.jpg" alt="Responsive Image"
srcset="image-small.jpg 480w,
image-medium.jpg 800w,
image-large.jpg 1200w"
sizes="(max-width: 600px) 480px,
(max-width: 900px) 800px,
1200px"
/>
在上面的示例中,srcset
属性指定了三个不同大小和分辨率的图像源,分别是image-small.jpg
、image-medium.jpg
和image-large.jpg
。每个图像源后面的数字(如480w
、800w
、1200w
)表示图像的宽度。
sizes
属性指定了在不同视口宽度下应该使用的图像大小。通过使用媒体查询,可以在不同的视口尺寸下为图像指定不同的大小。
当浏览器根据设备的屏幕大小和分辨率选择加载图像时,它会根据srcset
属性和sizes
属性的规则选择最合适的图像源,并自动调整图像的大小。
这样,使用srcset
属性可以为不同设备和视口尺寸提供最佳的图像质量和性能,实现响应式的图像展示。
我们可以使用min-height
和min-width
CSS属性分别设置元素的最小高度和最小宽度。它们可以防止元素变得比指定的大小更小,无论它包含多少内容。
可以使用任何长度单位(如像素)或百分比来指定大小,例如:
div {
min-height: 300px;
min-width: 400px;
}
这种解决方案适用于不需要响应式大小而是固定高度或宽度的元素。
我们的网站是否显示第三方广告?网站上最常见的做法是在加载期间或加载后动态添加广告内容。在页面的其余部分继续加载时,非广告内容可能会对用户可见。
如果没有为即将到来的广告预留足够的空间,它们可能会在到达时移动可见的非广告内容,这会导致较高的CLS
。以下是我们可以解决此问题的方法:
<div>
标签为静态广告预留适当的空间。有效的动画和过渡可以通过平滑地更新页面上的内容而不引起任何惊喜来提升用户体验。
内容突然和不可预测地移动几乎总会导致糟糕的用户体验,但是从一个位置逐渐自然地移动到另一个位置的内容可以帮助用户理解变化。
❝总的来说,在高CLS得分方面有两个主要的元凶:媒体文件和广告。 ❞
「分享是一种态度」。
参考资料:
[1]
核心网络指标: https://web.dev/vitals/
[2]
谷歌文档: https://web.dev/optimize-cls/
[3]
Lighthouse: https://developer.chrome.com/docs/lighthouse/overview/
[4]
Webpagetest: https://www.webpagetest.org/
[5]
Chrome DevTools: https://developer.chrome.com/docs/devtools/
[6]
Chrome Web Vitals扩展程序: https://chrome.google.com/webstore/detail/web-vitals/ahfhijdlegdabablpippeagghigmibma?hl=en
[7]
Google的BigQuery: https://cloud.google.com/bigquery
[8]
Google Data Studio: https://lookerstudio.google.com/u/0/
[9]
PageSpeed Insights: https://pagespeed.web.dev/?utm_source=psi&utm_medium=redirect
[10]
CrUX API: https://web.dev/chrome-ux-report-api/
[11]
Google Search Console: https://search.google.com/search-console/welcome
[12]
PageSpeed Insights: https://developers.google.com/speed/pagespeed/insights/
[13]
CLS优化: https://www.elegantthemes.com/blog/wordpress/cumulative-layout-shift-cls-what-it-is-how-to-optimize-your-website-for-it
[14]
CLS: https://www.onely.com/blog/cumulative-layout-shift/
[15]
核心 Web 指标: https://web.dev/vitals/
[16]
CSS百分比padding实现比例固定图片自适应布局: https://www.zhangxinxu.com/wordpress/2017/08/css-percent-padding-image-layout/
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有