为什么我的页面CLS总是很高,明明没做什么动态内容? 技术风云 提问于 2026-02-24 15:48:20 阅读 34 前端 最近用Lighthouse测性能,发现累积布局偏移(CLS)分数特别差,经常超过0.25。我页面里其实没加什么广告或者异步图片,就是普通的商品列表,每个商品有个标题和价格。 我试过给图片加了固定宽高,也用了aspect-ratio,但CLS还是不稳定。有时候刷新一下就高,再刷又正常了,完全搞不懂是哪里在动。有没有可能是字体加载导致的?我用的是Google Fonts。 性能指标视觉稳定 我来解答 赞 7 收藏 分享 生成中... 手机扫码查看 复制链接 生成海报 反馈 发表解答 您需要先 登录/注册 才能发表解答 2 条解答 Tr° 亚楠 Lv1 这个问题我太熟悉了,十有八九就是字体加载搞的鬼。你已经排除了图片和动态内容,那CLS不稳定大概率是字体切换时产生的跳动。 先说说原理:浏览器加载Google Fonts的时候,默认行为是先显示fallback字体(比如系统默认的宋体/黑体),等web字体下载完再替换成你指定的字体。这一替换,文本的宽高就变了,周围的元素自然就被挤来挤去,CLS就上去了。而且因为网络情况不同,有时候快有时候慢,所以你的CLS分数时高时低。 解决思路有几个,按我说的顺序来试: 第一步:加上font-display属性,这是最快最有效的办法。在Google Fonts的link里加上display=swap参数: <link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link href="https://fonts.googleapis.com/css2?family=你的字体&display=swap" rel="stylesheet"> display=swap的意思是:字体下载期间先用fallback字体显示,下载完成后立刻换成目标字体。这样虽然可能有轻微的字体切换感,但至少不会产生大幅度的布局偏移。 第二步:如果第一步不够,或者你想更讲究一点,可以预加载字体。把它放在HTML的最前面,让浏览器提前开始下载: <head> <link rel="preload" href="https://fonts.googleapis.com/css2?family=你的字体" as="style"> <link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> ... </head> 第三步:如果你的字体切换后文字大小差异很大,还可以调整fallback字体。用CSS的size-adjust让fallback字体和目标字体更接近,这样切换时视觉差异小: @font-face { font-family: 'MyFont'; src: url('/fonts/myfont.woff2') format('woff2'); font-display: swap; ascent-override: 90%; descent-override: 20%; size-adjust: 95%; } 这几个参数需要你根据实际情况微调,ascent-override和descent-override控制字体的上下留白,size-adjust整体缩放fallback字体。 你可以先从第一步开始试,一般就能解决大部分问题了。如果还有问题,再配合第二步第三步。 回复 点赞 2026-03-11 19:09 设计师景岩 Lv1 你这个情况我太熟悉了,十有八九就是 Google Fonts 的字体加载问题,尤其是中文字体文件特别大,加载时会先显示一个系统字体(比如 Helvetica 或 Arial),等字体加载完了再突然切换成你指定的字体,导致文字高度、宽度变化,CLS 就崩了。 先确认下是不是这个原因:打开 DevTools 的 Network 面板,勾选 Disable cache,然后刷新页面,看字体文件是不是在首屏就加载,而且加载时间比较长(比如超过 200ms)。 解决方案很简单,给字体加 font-display: swap,再配合 preconnect 和 preload,代码给你: <link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link href="https://fonts.googleapis.com/css2?family=Your+Font:wght@400;700&display=swap" rel="stylesheet"> CSS 里别忘了写 font-display: swap,如果你是用 Google Fonts 的链接,其实加了 display=swap 就自动生效了,但保险起见你可以在 CSS 里再确认下: body { font-family: 'Your Font', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; font-display: swap; /* 如果是通过 CSS @import 的话 */ } 不过更推荐用 link 标签引入,别用 @import,后者会阻塞渲染。 另外,如果你页面里有动态插入的元素(比如某个 JS 300ms 后才插入一个广告位或者提示条),也会导致 CLS 飙升,建议用 Chrome 的 Performance 面板录一段加载过程,看 Layout Shift Regions 里具体是哪块在动,一般都能定位到。 实在不行,临时加个: * { max-lines: 3; /* 或者用 min-height / min-width 固住容器 */ } 把可能塌陷的区域先占位住,也能缓解,但治标不治本,还是优先解决字体加载的问题。 回复 点赞 6 2026-02-24 16:11 加载更多 相关推荐 2 回答 41 浏览 为什么我的页面布局偏移导致CLS很高? 我最近用Lighthouse测性能,发现CLS(累积布局偏移)特别高,明明没加什么动态内容啊。仔细看发现是图片加载时撑开了布局,但我已经给img加了width和height属性了,怎么还是有偏移? 这... 司空雨路 前端 2026-02-27 12:58:23 1 回答 5 浏览 Lighthouse 报告中 CLS 值很高,但页面看起来没跳动? 我用 Lighthouse 测了一个页面,CLS(累积布局偏移)得分特别低,说是 0.35,但我在浏览器里反复刷新根本看不出内容有突然跳动啊。是不是哪里误报了? 页面里确实有个图片没设宽高,但我加了 ... UP主~冬冬 工具 2026-03-18 22:54:26 1 回答 23 浏览 图片懒加载时为什么CLS值还是很高? 我在做图片列表页时用了懒加载,给标签设置了固定宽高和object-fit: cover,但Lighthouse检测CLS还是0.2以上。页面滚动到图片位置时偶尔还是会抖动,试过加loading="la... 司空鹏宇 前端 2026-02-17 13:59:25 2 回答 51 浏览 图片加载导致CLS分数高,怎么定位和修复? 开发图片列表页时,Lighthouse报告显示CLS有0.5以上,主要问题提示“避免不必要的布局 shifting”。图片都用了懒加载,给img标签设置了固定宽高,但分数还是很高,搞不懂哪里出问题了。... ♫慧慧 工具 2026-02-14 22:34:00 2 回答 31 浏览 Sapper中动态路由页面为什么在客户端首次加载时显示空白? 折腾了一下午也没解决,我在Sapper的动态路由里写了一个博客详情页,服务器端渲染正常,但直接访问客户端时页面内容全白。 代码是这样的: <!-- routes/_posts/[slug].sv... 小斯羽 框架 2026-02-14 11:16:36 2 回答 31 浏览 为什么用querySelectorAll选不到动态生成的元素? 我给页面添加动态元素后用querySelectorAll('.item')总是返回空列表,明明元素在DOM里能看到... 场景是点击按钮动态创建,然后立刻用document.querySelector... Designer°明轩 前端 2026-02-10 05:57:22 2 回答 24 浏览 表单提交后页面为什么会自动刷新? 我在用原生 JavaScript 处理表单提交,但每次点击提交按钮,页面都会自动刷新,导致我刚填的数据全没了。明明我已经加了 event.preventDefault() 啊,怎么还是不行? 这是我的... 书生シ紫晨 交互 2026-03-02 23:25:19 2 回答 25 浏览 Vue组件里动态设置SEO标题和meta标签为什么没效果? 我在用Vue 3开发博客页面时,想在组件里动态设置SEO标题和description标签。按照文档用了vue-meta插件,但页面加载后这些标签都没渲染出来,浏览器标题还是默认的"Vue App"。 ... 夏侯威威 前端 2026-02-19 12:31:25 2 回答 88 浏览 Taro项目适配快应用时为什么页面布局显示错位? 我在用Taro开发多端应用时,适配快应用遇到了问题。页面布局在其他平台都正常,但在快应用里总是显示错位,比如导航栏和内容区域挤在一起。之前调整过flex布局的justify-content和align... IT人梓艺 框架 2026-02-18 12:51:32 2 回答 57 浏览 为什么我的Service Worker缓存策略导致页面刷新后内容没更新? 最近给项目加了Service Worker做静态资源缓存,但发现更新了JS文件后页面一直显示旧版本。明明已经用cache.first策略,还手动调用了clients.claim()和skipWaiti... 公孙凡敬 优化 2026-02-16 04:43:34
先说说原理:浏览器加载Google Fonts的时候,默认行为是先显示fallback字体(比如系统默认的宋体/黑体),等web字体下载完再替换成你指定的字体。这一替换,文本的宽高就变了,周围的元素自然就被挤来挤去,CLS就上去了。而且因为网络情况不同,有时候快有时候慢,所以你的CLS分数时高时低。
解决思路有几个,按我说的顺序来试:
第一步:加上font-display属性,这是最快最有效的办法。在Google Fonts的link里加上display=swap参数:
display=swap的意思是:字体下载期间先用fallback字体显示,下载完成后立刻换成目标字体。这样虽然可能有轻微的字体切换感,但至少不会产生大幅度的布局偏移。
第二步:如果第一步不够,或者你想更讲究一点,可以预加载字体。把它放在HTML的最前面,让浏览器提前开始下载:
第三步:如果你的字体切换后文字大小差异很大,还可以调整fallback字体。用CSS的size-adjust让fallback字体和目标字体更接近,这样切换时视觉差异小:
这几个参数需要你根据实际情况微调,ascent-override和descent-override控制字体的上下留白,size-adjust整体缩放fallback字体。
你可以先从第一步开始试,一般就能解决大部分问题了。如果还有问题,再配合第二步第三步。
先确认下是不是这个原因:打开 DevTools 的 Network 面板,勾选 Disable cache,然后刷新页面,看字体文件是不是在首屏就加载,而且加载时间比较长(比如超过 200ms)。
解决方案很简单,给字体加
font-display: swap,再配合preconnect和preload,代码给你:CSS 里别忘了写
font-display: swap,如果你是用 Google Fonts 的链接,其实加了display=swap就自动生效了,但保险起见你可以在 CSS 里再确认下:不过更推荐用 link 标签引入,别用 @import,后者会阻塞渲染。
另外,如果你页面里有动态插入的元素(比如某个 JS 300ms 后才插入一个广告位或者提示条),也会导致 CLS 飙升,建议用 Chrome 的 Performance 面板录一段加载过程,看 Layout Shift Regions 里具体是哪块在动,一般都能定位到。
实在不行,临时加个:
把可能塌陷的区域先占位住,也能缓解,但治标不治本,还是优先解决字体加载的问题。