简体   繁体   English

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

[英]Cumulative Layout Shift with Bootstrap 4 grid

I am having a problem with high CLS (Content Layout Shift) while using Bootstrap (4.5) grid for two column layout with column order change.在将 Bootstrap (4.5) 网格用于两列布局并更改列顺序时,我遇到了高 CLS(内容布局移位)的问题。

CLS is a Core Web Vital metric. CLS是一个 Core Web Vital 指标。 Basically Google sees a problem when webpage's parts are moving when the page is loading.基本上,当页面加载时网页部分移动时,Google 会发现问题。 Supposedly this metric is to affect SEO.据说这个指标会影响搜索引擎优化。

On high resolutions my layout consists of two columns.在高分辨率下,我的布局由两列组成。 Main content on the right and sidebar on the left.右侧的主要内容和左侧的侧边栏。 On lower resolutions sidebar content is pushed down below main content.在较低分辨率下,侧边栏内容被推到主要内容下方。 So HTML looks like this:所以 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>

The problem is that for brief moment while the page renders on desktops, the main content appears on the left side, then milliseconds later it shifts to the right place on the right.问题是,当页面在桌面上呈现时,主要内容出现在左侧的短暂时间,然后几毫秒后它转移到右侧的正确位置。 With simple pages (with simple DOM or no external resources) the shift is not detectable.对于简单的页面(具有简单的 DOM 或没有外部资源),这种转变是无法检测到的。

I've prepared an example of such page .我准备了一个这样的页面例子 (The source code is on github ). 源代码在 github 上)。 To measure CLS I am using Lighthouse in Chrome.为了测量 CLS,我在 Chrome 中使用 Lighthouse。 In my case when I refresh the page I can see columns moving and Lighthouse informs me of CLS value of 0.326.在我的情况下,当我刷新页面时,我可以看到列在移动,并且 Lighthouse 通知我 CLS 值为 0.326。 The result might depend on rendering resources so you might get something different.结果可能取决于渲染资源,因此您可能会得到不同的结果。 But it seems Google Page Insight gives similar result:但似乎Google Page Insight给出了类似的结果:

在此处输入图片说明

Anyway, is there a way to avoid such shift while the page renders?无论如何,有没有办法在页面呈现时避免这种转变?

It seems the problem is more Chrome related then flexbox or bootstrap.似乎问题更多地与 Chrome 相关,然后是 flexbox 或 bootstrap。 It turned out that the problem is caused by premature renderation.原来问题是过早渲染造成的。 Chrome's parser "yields" (so it triggers rendering): Chrome 的解析器“产生”(因此它触发渲染):

  • after reading 65536 bytes of data,读取65536字节数据后,
  • after encountering <script> tag after reading 50 "tokens" (which I think are basically html tags).在阅读 50 个“令牌”(我认为基本上是 html 标签)后遇到<script>标签后。

The example I provided shows the first case (but actually my real website experiences CLS because the second one).我提供的示例显示了第一种情况(但实际上我的真实网站经历了 CLS,因为是第二种情况)。 Both of those cases have "bugs" related to them submitted: 1130290 and 1041006 .这两个案例都提交了与它们相关的“错误”: 11302901041006

So the answer to the problem is hoping that the "bugs" will get resolved.所以问题的答案是希望“错误”得到解决。 In the meantime depending on actual cause you can limit file size or remove <script> tags.同时,根据实际原因,您可以限制文件大小或删除<script>标签。

Short Answer简答

Minimise the HTML and the problem seems to go away.最小化 HTML,问题似乎消失了。

Longer Answer更长的答案

I did a bit of digging, this isn't a complete "this is exactly what happens" answer but I got enough of an idea to come up with the above solution and to roughly explain my reasoning.我做了一些挖掘,这不是一个完整的“这正是发生的事情”的答案,但我有足够的想法来提出上述解决方案并粗略地解释我的推理。 I am hoping someone can expand upon the gaps in my knowledge.我希望有人可以扩大我的知识差距。

So what made me come up with the above solution?那么是什么让我想出了上述解决方案?

After profiling the page load I notice that there were 2 HTML parse tasks being created.在分析页面加载后,我注意到创建了 2 个 HTML 解析任务。

One dealt with lines 1-770 of the HTML and the other dealt with lines 771 to the end of the document.一个处理 HTML 的第 1-770 行,另一个处理文档末尾的第 771 行。

Because of this the page appears to render the first 770 lines and then recalculates the layout on the second HTML parse task because you have swapped the order (and the .col-lg-4 column is in the second parsing pass HTML).因此,页面似乎呈现前 770 行,然后在第二个 HTML 解析任务上重新计算布局,因为您已经交换了顺序(并且.col-lg-4列在第二个解析传递 HTML 中)。

You won't see this on a "normal" page as if the page is rendered in DOM order layouts will be correct anyway and the second HTML parsing pass will just add more detail to the layout.您不会在“普通”页面上看到这一点,因为页面以 DOM 顺序呈现,布局无论如何都是正确的,第二个 HTML 解析过程只会向布局添加更多细节。

As it appeared to be pretty consistent where it cut the page off I removed all line breaks and white space.由于它在切断页面的位置看起来非常一致,因此我删除了所有换行符和空格。 My theory being that whatever algorithm is deciding where to split the HTML up is using line number as part of that calculation.我的理论是,无论决定在何处拆分 HTML 的算法都使用行号作为该计算的一部分。

By reducing the effective lines to 15 or so I was hoping to make that algorithm only parse the HTML in one pass.通过将有效行减少到 15 行左右,我希望使该算法仅在一次传递中解析 HTML。

It actually still does it in 2 but the last pass is the closing </html> tag only so doesn't matter.它实际上仍然在 2 中执行,但最后一次传递只是结束</html>标记,因此无关紧要。 The result of this is when the parsed HTML is combined with the CSSOM it can calculate the layout correctly.这样做的结果是当解析的 HTML 与 CSSOM 结合时,它可以正确计算布局。

a bit of a hack but it should work up to certain page depths.有点hack,但它应该可以工作到特定的页面深度。

please note - if I doubled the DOM node count this workaround did not work again.请注意- 如果我将 DOM 节点数加倍,则此解决方法不再起作用。 If I changed the length of each list item (ie put lorem ipsum in) but didn't change the structure it did not make a difference.如果我更改了每个列表项的长度(即放入 lorem ipsum)但没有更改结构,则没有任何区别。 So it appears to be some combination of number of DOM elements and line number that decides when the HTML parser should stop its first pass.因此,似乎是 DOM 元素数量和行号的某种组合决定了 HTML 解析器何时应该停止其第一次传递。

A possible solution一个可能的解决方案

Go back to old layout models.回到旧的布局模型。 If you use float:left and float:right it should work.如果您使用float:leftfloat:right它应该可以工作。 I think this specific issue is a combination of page complexity (number of DOM nodes) and using flexbox.我认为这个特定问题是页面复杂性(DOM 节点的数量)和使用 flexbox 的组合。

With flexbox being slightly slower than old layout models and sometimes having to use multiple passes (old layout models are single pass) I would imagine this issue would not persist with the above recommendation.由于 flexbox 比旧的布局模型稍慢,有时不得不使用多次传递(旧的布局模型是单次传递),我想这个问题不会在上述建议中持续存在。

Where I found out about multiple layout passes in certain scenarios 我在某些情况下发现多个布局传递的地方

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM