内容后到会推动已呈现元素
别名: 布局偏移 · layout shift · 后到内容推移 · 累积布局偏移
概念解释
已经画到屏幕上的节点,会因为迟到的内容被整体推开。这个现象叫布局偏移(layout shift):不是页面“加载得慢”,而是第二次布局改写了第一次已经交给屏幕的几何。浏览器给现有节点分配过 used box 之后,广告条、推荐卡、提示条或任何后插入、后变高的块一旦进入文档流,跟在后面的盒子必须重新计算位置。用户看见的是已呈现元素在动,不是空白在填满。
机制
文档流是一条几何约束链。每个 in-flow 盒子的纵向起点依赖前面兄弟的已用高度;横向位置依赖容器和浮动。第一次布局在缺内容时把这条链闭合,像素已经提交。第二次布局在内容到达后重开同一条链,所有排在插入点之后的节点发生位移。位移量是两棵布局树里同一节点视觉矩形的差,不是资源下载耗时本身。
累积布局偏移(CLS, Cumulative Layout Shift)把用户未预期的位移按影响面积加权累计。用户自己点开造成的位移通常不计为意外。决定偏移是否发生的,是迟到内容有没有改变已绘制节点的位置;资源何时到达只决定这件事发生在第几帧。
怎么研究
实验室合成一次加载(Lighthouse 一类)给出 CLS;现场数据(CrUX 或自有 RUM)记录真实会话窗口里的偏移。二者经常出现 metric mismatch:实验室常屏蔽第三方脚本、使用缓存字体,现场才有迟到的广告位和字体交换。自变量包括插入节点相对已绘内容的位置、插入延迟、容器是否已有确定尺寸。因变量是 CLS、单次最大位移分数、以及 layout-shift 条目里的 source 节点。实验室分数不能直接写成现场承诺,因为会话长度和第三方时序不同。
边界
用户主动展开的手风琴、自己触发的插入,不算意外偏移。脱离文档流的覆盖层不推动后续节点,但可能挡住控件——那是遮挡,不是推移。只发生在当前视口外的位移用户看不见,也不进入 CLS。若预渲染或打印快照在内容齐套之后才展示,推动发生在看见之前,对这次展示不成立。
怎么落地
- 会变高的插槽在第一次布局前给出确定高度或宽高比,让迟到内容填进已有盒子,而不是把邻居顶走。
- 禁止在已绘制的正文起点或主操作条上方再插入新的 in-flow 块。
- 用
PerformanceObserver订阅layout-shift,过滤hadRecentInput,按 source 节点追查谁在推。 - 验证:冷加载加节流网络录屏,逐帧标出已绘节点的位移;把现场 CLS 分位和实验室对照,差出来的来源逐条关掉。