Back

使用现代 CSS 防止布局偏移

使用现代 CSS 防止布局偏移

意外的内容跳动会让用户感到沮丧,并损害您的核心 Web 指标得分。累积布局偏移(CLS)衡量的是这些令人不适的移动——不仅仅是在初始加载期间,而是贯穿整个页面会话。您即将点击的按钮突然移动了。文本在字体切换时重排。嵌入内容在滚动过程中将内容向下推。

现代 CSS 为您提供了精确的工具,可以在布局偏移发生之前就将其防止。本文介绍了目前在生产环境中有效的 CSS 优先技术,重点关注固有尺寸、字体稳定性以及能够将 CLS 得分保持在 0.1 阈值以下的动画模式。

核心要点

  • CLS 在整个页面生命周期中累积,而不仅仅是在初始加载期间——真实用户监控通常会显示比实验室工具更高的得分
  • 使用 aspect-ratiowidthheight 属性声明固有尺寸,以在内容到达之前预留空间
  • @font-face 声明中使用 size-adjust 和度量覆盖属性来消除字体切换重排
  • 仅对 transformopacity 属性进行动画处理,以避免触发布局重新计算

为什么 CLS 会延伸到页面加载之后

CLS 在整个页面生命周期中累积。像 Lighthouse 这样的实验室工具捕获加载时的偏移,但真实用户监控(RUM)通常会显示更高的得分。差异在哪里?来自延迟加载内容、后期注入广告或超过用户交互后 500 毫秒宽限期的过渡所产生的加载后偏移。

在符合条件的用户输入后 500 毫秒内发生的偏移不计入 CLS——它们是预期的。其他所有情况都会计入。这意味着滚动触发的延迟加载、调整元素大小的悬停状态以及客户端路由过渡,如果它们导致意外移动,都会产生影响。

使用固有尺寸预留空间

防止布局偏移的基础是在内容到达之前声明尺寸。现代 CSS 使这变得简单直接。

图像和媒体

aspect-ratio 属性让浏览器仅使用比例就能预留空间,无需固定像素值。结合 <img> 元素上的 widthheight 属性,浏览器在 HTML 解析期间就能立即计算预留空间。

对于响应式图像,在 <picture> 内的 <source> 元素上设置尺寸,以处理艺术指导而不产生偏移。浏览器在任何图像数据下载之前使用这些值来建立宽高比。

嵌入内容和动态内容

第三方嵌入内容——视频、地图、社交帖子——很少传达其最终尺寸。在容器元素上使用 min-heightaspect-ratio 来预留预期空间。当确切尺寸未知时,根据您的分析数据为最常见的尺寸预留空间,接受异常值的轻微偏移。

对于通过 JavaScript 注入的内容,同样的原则适用:容器应该在脚本执行之前在 CSS 中声明固有尺寸。

无重排的字体加载

当备用字体和最终字体具有不同的度量时,Web 字体会导致偏移。仅使用 font-display 属性无法解决这个问题——当度量不同时,swap 仍然会导致重排。

度量对齐的备用字体

现代 CSS 在 @font-face 声明中提供了 size-adjustascent-overridedescent-overrideline-gap-override。这些属性调整备用字体的度量以匹配您的 Web 字体,即使在发生切换时也能消除可见的重排。

将其与 font-display: optional 配对以实现最严格的 CLS 防护——Web 字体仅在初始布局期间可用时才渲染。对于不那么激进的方法,度量覆盖与 font-display: swap 结合使用可以立即提供可读文本,同时最小化偏移幅度。

使用 <link rel="preload"> 预加载关键字体可以增加它们在首次绘制时可用的机会,减少显示备用字体的时间窗口。

动画和 UI 扩展

widthheighttopleftmargin 进行动画处理会触发布局重新计算并影响 CLS。对 transformopacity 进行动画处理则不会——这些属性在合成器上运行,不影响文档流。

安全的动画模式

使用 transform: scale() 缩放元素,而不是改变尺寸。使用 transform: translate() 移动元素,而不是位置属性。这些方法创建视觉移动而不会偏移周围的内容。

对于扩展 UI——手风琴、下拉菜单、工具提示——如果扩展在用户交互后 500 毫秒内发生,则偏移是可接受的。如果扩展是自动发生或延迟后发生,则预先预留最大扩展空间,或使用 position: absolute 或覆盖模式将扩展元素定位在文档流之外。

路由变化时的过渡

单页应用程序在客户端导航期间经常触发 CLS。如果过渡动画超过 500 毫秒或内容在导航后异步加载,偏移会计入您的得分。保持过渡简短,并确保传入内容通过骨架占位符或固定容器尺寸预留了空间。

验证您的方法

Chrome DevTools 的性能面板显示各个布局偏移及其得分和受影响的元素。布局偏移轨道可视化偏移集群,帮助识别模式。

对于生产监控,使用 web-vitals 库的 RUM 解决方案可以捕获具有元素归因的真实用户 CLS。将现场数据与实验室测量进行比较——差异表明您的合成测试遗漏了加载后偏移。

结论

防止布局偏移归结为一个原则:在渲染之前为所有内容声明固有尺寸。对媒体使用 aspect-ratio,对字体使用度量覆盖,对动画使用 transform。为延迟加载的内容预留空间,并使用实验室工具和现场数据进行验证。

用于 CLS 防护的现代 CSS 不是关于技巧——而是关于为浏览器提供从一开始就正确分配空间所需的信息。

常见问题

Google 认为 CLS 得分低于 0.1 为良好,0.1 到 0.25 之间需要改进,高于 0.25 为差。目标是将得分保持在 0.1 以下,以获得最佳用户体验和核心 Web 指标性能。监控实验室和现场数据,因为真实用户得分通常与合成测试不同。

Lighthouse 仅在受控条件下的页面加载期间测量 CLS。真实用户监控捕获整个会话期间的偏移,包括延迟加载的内容、后期注入的广告和用户交互。在 Lighthouse 完成测量后发生的加载后偏移只会出现在现场数据中。

不能,仅使用 font-display swap 无法防止布局偏移。它确保在字体加载期间文本保持可见,但当 Web 字体替换备用字体时仍会导致重排。要防止偏移,请将其与度量覆盖属性(如 size-adjust、ascent-override 和 descent-override)结合使用,以匹配备用字体和 Web 字体的度量。

不会。使用 transform 和 opacity 属性的动画在合成器线程上运行,不影响文档流,因此不会导致布局偏移。只有改变影响布局的属性(如 width、height、margin 或位置值)的动画才会触发重新计算并影响 CLS。

Truly understand users experience

See every user interaction, feel every frustration and track all hesitations with OpenReplay — the open-source digital experience platform. It can be self-hosted in minutes, giving you complete control over your customer data. . Check our GitHub repo and join the thousands of developers in our community..

OpenReplay