使用 Bootstrap 4 网格进行累积布局转换

szy*_*ond 10 css lighthouse flexbox bootstrap-4 pagespeed-insights

在将 Bootstrap (4.5) 网格用于两列布局并更改列顺序时,我遇到了高 CLS(内容布局移位)的问题。

CLS是一个 Core Web Vital 指标。基本上,当页面加载时网页部分移动时,Google 会发现问题。据说这个指标会影响搜索引擎优化。

在高分辨率下,我的布局由两列组成。右侧的主要内容和左侧的侧边栏。在较低分辨率下,侧边栏内容被推到主要内容下方。所以 HTML 看起来像这样:

<div class="container-fluid">
    <div class="row">
        <div class="col-lg-8 order-lg-2">
        </div>
        <div class="col-lg-4 order-lg-1">
        </div> 
    </div> 
</div>
Run Code Online (Sandbox Code Playgroud)

问题是,当页面在桌面上呈现时,主要内容出现在左侧的一小段时间内,然后几毫秒后它转移到右侧的正确位置。对于简单的页面(具有简单的 DOM 或没有外部资源),这种转变是无法检测到的。 

我准备了一个这样的页面例子。(源代码在 github 上)。为了测量 CLS,我在 Chrome 中使用 Lighthouse。在我的情况下,当我刷新页面时,我可以看到列在移动,并且 Lighthouse 通知我 CLS 值为 0.326。结果可能取决于渲染资源,因此您可能会得到不同的结果。但似乎Google Page Insight给出了类似的结果:

在此处输入图片说明

无论如何,有没有办法在页面呈现时避免这种转变? 

szy*_*ond 6

似乎问题更多地与 Chrome 相关,然后是 flexbox 或 bootstrap。原来问题是过早渲染造成的。Chrome 的解析器“产生”(因此它触发渲染): 

  • 读取65536字节数据后, 
  • <script>阅读 50 个“令牌”(我认为基本上是 html 标签)后遇到标签后。

我提供的示例显示了第一种情况(但实际上我的真实网站经历了 CLS,因为是第二种情况)。这两个案例都提交了与它们相关的“错误”:11302901041006。 

所以问题的答案是希望“错误”得到解决。同时,根据实际原因,您可以限制文件大小或删除<script>标签。     


Gra*_*hie 0

简答

最小化 HTML,问题似乎就消失了。

更长的答案

我做了一些挖掘,这不是一个完整的“这正是发生的情况”的答案,但我有足够的想法来提出上述解决方案并粗略地解释我的推理。我希望有人能够弥补我的知识空白。

那么是什么让我想出了上述解决方案呢?

对页面加载进行分析后,我注意到创建了 2 个 HTML 解析任务。

一个处理 HTML 的第 1-770 行,另一个处理第 771 行到文档末尾。

因此,页面似乎呈现前 770 行,然后重新计算第二个 HTML 解析任务的布局,因为您交换了顺序(并且该.col-lg-4列位于第二个解析过程 HTML 中)。

您不会在“正常”页面上看到这一点,就好像该页面以 DOM 顺序渲染一样,无论如何布局都是正确的,并且第二个 HTML 解析过程只会向布局添加更多细节。

由于它在切断页面的地方看起来非常一致,所以我删除了所有换行符和空白。我的理论是,无论决定在哪里分割 HTML 的算法都是使用行号作为计算的一部分。

通过将有效行减少到 15 行左右,我希望使该算法仅一次性解析 HTML。

它实际上仍然在 2 中执行,但最后一次传递</html>只是结束标记,所以并不重要。其结果是,当解析的 HTML 与 CSSOM 结合时,它可以正确计算布局。

有点破解,但它应该可以工作到一定的页面深度。

请注意- 如果我将 DOM 节点数加倍,此解决方法将不再起作用。如果我更改了每个列表项的长度(即放入 lorem ipsum )但没有更改结构,则不会产生任何影响。因此,似乎是 DOM 元素数量和行号的某种组合决定了 HTML 解析器何时应停止其第一遍。

一个可能的解决方案

返回到旧的布局模型。如果你使用float:leftfloat:right应该可以工作。我认为这个具体问题是页面复杂性(DOM 节点数量)和使用 Flexbox 的结合。

由于 Flexbox 比旧的布局模型稍慢,并且有时必须使用多次传递(旧的布局模型是单次传递),我想按照上述建议,这个问题不会持续存在。

我在哪里发现了某些场景下的多个布局过程