Bootstrap 4网格的累积版式移位

时间:2020-09-13 09:48:04

标签: css bootstrap-4 flexbox lighthouse pagespeed-insights

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

CLS是一项核心网络生命指标。基本上,当网页加载时,网页的各个部分在移动时,Google会看到问题。据说该指标会影响SEO。

在高分辨率下,我的布局由两列组成。右侧为主要内容,左侧为侧边栏。在较低分辨率下,侧边栏内容被下推至主要内容下方。 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>

问题在于,页面在桌面上呈现时,一会儿,主要内容显示在左侧,然后毫秒(稍后),页面移到右侧的右侧。对于简单的页面(具有简单的DOM或没有外部资源),无法检测到该偏移。

我准备了example of such page。 (source code is on github)。为了测量CLS,我在Chrome中使用Lighthouse。就我而言,当我刷新页面时,我可以看到列正在移动,并且Lighthouse会通知我CLS值为0.326。结果可能取决于渲染资源,因此您可能会有所不同。但是似乎Google Page Insight给出了类似的结果:

enter image description here

无论如何,有没有一种方法可以避免在页面渲染时出现这种偏移?

3 个答案:

答案 0 :(得分:1)

问题似乎更多是与Chrome有关,而不是flexbox或bootstrap。事实证明,该问题是由过早渲染引起的。 Chrome的解析器会``屈服''(因此会触发渲染):

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

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

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

答案 1 :(得分: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的速度比旧布局模型慢一些,并且有时不得不使用多次通过(旧布局模型是单次通过),我想这个问题在上述建议中将不会持续。

Where I found out about multiple layout passes in certain scenarios

答案 2 :(得分:-1)

这与Bootstrap无关,但这完全是由于Critical CSS的使用不正确或使用不正确。

简而言之,关键CSS将仅加载上述视口中所需的CSS。所有其他CSS(引导框架)都将被延迟(使用defer属性)。

我看到您已经实现了关键的CSS(头部是内联样式),但是加载了所有可用的Bootstrap CSS(或很大一部分),使页面大约80kb大,而其中仅包含一些简单的CSS / HTML。

这个想法是只加载所需的CSS,在您的示例中,仅加载您所使用的网格类的CSS(以及一些基本的html元素样式)。因此,类似这样的东西(只有几kb且加载速度更快):

*,::after,::before{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:left;background-color:#fff}h1,h3{margin-top:0;margin-bottom:.5rem}ul{margin-top:0;margin-bottom:1rem}a{color:#007bff;text-decoration:none;background-color:transparent}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}h1,h3{margin-bottom:.5rem;font-weight:500;line-height:1.2}h1{font-size:2.5rem}h3{font-size:1.75rem}.container-fluid{width:100%;padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.row{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-right:-15px;margin-left:-15px}.col-lg-4,.col-lg-8{position:relative;width:100%;padding-right:15px;padding-left:15px}@media (min-width:992px){.col-lg-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-lg-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.order-lg-1{-ms-flex-order:1;order:1}.order-lg-2{-ms-flex-order:2;order:2}}

您还可以使用tools在线生成此关键CSS,或使用penthouse将其集成到您的webpack / gulp工作流程中。

如果您将上述CSS内联加载到头部并像下面在页脚中那样加载所有引导程序deferred,我认为Pagespeed CLS将会有所改善!

<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" defer="defer">