消除阻止页面首屏渲染的CSS代码

156
我一直在使用Google PageSpeed Insights来尝试提高我的网站性能,至今为止它已经非常成功。像推迟脚本之类的操作非常有效,因为我已经有了jQuery中 .ready() 的内部版本来推迟脚本,直到页面完全加载,所以我只需要将特定函数嵌入行内并将完整脚本移到页面末尾。这个方法非常好用。
但现在我发现自己盯着清单上剩下的那一个黄色圆点看:“消除以上折叠内容中阻塞呈现的CSS”。
我的CSS设置的方式是有一个全局的 _.css 文件包含适用于页面结构的样式,或者在整个网站上使用一两次。然后大多数页面都有一个相关联的CSS文件(例如,party.phpparty.css )包含特定于该页面的样式。所有CSS文件都被无限期地缓存,因为我将/t=FILEMTIME添加到文件名中(稍后通过.htaccess文件删除),以确保文件在修改时更新。
然后,Google建议内联关键样式以用于折叠内容。问题是...看一下这个屏幕截图:http://prntscr.com/1qt49e
如你所见...所有内容都在上折叠区域!人们不喜欢滚动,尤其是在需要加载许多页面的游戏中。因此我设计了网站以适合一个屏幕(假设分辨率足够好)。这意味着...所有样式都适用于上折叠内容!那么...有没有什么解决办法?还是说我被卡在一个否则得分接近完美的黄色标记中了?

具有讽刺意味的是,屏幕截图的上折叠内容加载时间很长 :) 实际上,对我来说,屏幕截图最终从未加载成功。 - Anupam
@Anupam 可能已被删除。Prntscr并不是为了永久保存而设计的,我也没想到这个问题会如此受欢迎。 - Niet the Dark Absol
是的,一切都好,只是一个轻松的评论。 - Anupam
7个回答

187
之前已经有人问过类似的问题:Google Pagespeed中“above-the-fold content”是什么意思? 首先需要注意的是这都是关于移动页面的事情。
所以如果我正确地理解了你的问题和截图,那么这不适用于你的网站!
相反,按照谷歌的建议做一些事情会使“普通”网站的情况变得更糟。
而且并不是谷歌提出的所有东西都是“圣杯”,只因为它来自谷歌。如果你看看他们的HTML标记,他们本身也不是一个好的榜样。
我可以给你最好的建议是:
  • 在你的CSS中设置替代元素的宽度和高度,这样浏览器就可以布局元素,而不必等待替换内容!
此外,为什么要使用不同的CSS文件,而不是只使用一个呢?
额外的请求比少量的数据容量更糟糕。而且在第一次请求后,CSS文件会被缓存。
人们应该始终注意以下几点:
  • 尽可能减少请求数量
  • 保持整体页面重量尽可能低
不要为了让你的网站得到Google的PageSpeed Insights工具的100%而困扰自己...!;-)
补充1:这是谷歌向我们展示优化CSS交付时推荐的页面。

如前所述,我认为这对于一个“普通”的网站来说既不现实,也没有意义!因为当你拥有响应式网页设计时,很可能会使用媒体查询和其他布局样式。因此,如果你不首先以阻塞的方式加载CSS,你将会得到FOUT(未经过样式处理的文本内容)。我真的不相信这比至少多渲染几毫秒页面更“好”!

在我看来,Google正在开始一场新的“炒作”(当我在Stackoverflow上看到所有与此相关的问题时)...!


9
好的回答。问题在于如果你的网页加载速度较慢,谷歌似乎会对你进行惩罚。因此,他们强制你遵守他们的理念,无论是好是坏。 :( - Steve Horvath
10
@Netsurfer,并不是所有来自谷歌的东西都是“圣杯”哈哈。在看到这条评论后,我一直在想办法达到100,但最终只停留在了92。 - kiranking
47
你应该更加强调这一事实,即谷歌不遵循他们自己的建议 - Mr. Smith
2
随着HTTP/2和SPDY的出现,额外的请求将不再成为问题。维基百科上指出:“在HTTP/2的第一份草案中(它是SPDY的一个副本),额外的性能改进来自于请求和响应的多路复用,以避免HTTP 1中的头阻塞问题(即使使用了HTTP管线化),头部压缩和请求优先级。” - RationalDev likes GoFundMonica
3
我会尽力为您翻译:我一直在尝试将我的页面移动设备得分提升至72,桌面得分提升至80,但是一直遇到同样的问题。我不想把我的CSS文件放置在较低位置,可能会导致FOUT(闪现无样式内容)出现,从而降低用户体验。 - publicknowledge
显示剩余7条评论

18

如何在Google Page Speed(移动端)上获得99/100分

简而言之:将整个CSS脚本压缩并嵌入到<style></style>标签之间。


我已经追逐那个难以捉摸的100/100分数差不多一周了。就像你一样,最后剩下的问题是消除“渲染阻塞CSS”。

肯定有一个简单的解决方法吧?没有。我试过了Filament group的loadCSS的解决方案,但里面涉及到太多的.js文件,我并不喜欢。

那么像js一样使用async属性来处理css呢?这是不可能的。

我准备放弃了。然后我意识到,如果将脚本作为链接阻止了渲染,那么如果我将整个css嵌入到<head>中会怎样呢?这样就没有什么可以阻止渲染的内容了。

我觉得在<style>标签中嵌入1263行CSS绝对是错误的。但是我还是尝试了一下。我使用以下命令将其压缩并添加前缀:

postcss -u autoprefixer --autoprefixer.browsers 'last 2 versions' -u cssnano --cssnano.autoprefixer false *.css -d min/请参阅NPM postcss包

现在,它只是一个没有空格的长行CSS代码。我将它放置在首页的<style>标签中:<style>your;great-wall-of-china-long;css;here</style>。然后我重新使用页面速度分析工具进行了分析。

从90/100提高到99/100(移动端)!!!

这违背了我的想法(可能也违背了你的想法)。但是它解决了问题。目前,我只在主页上使用它,并通过PHP include以编程方式包含压缩的CSS。

你的 CSS 长度会影响结果(具体情况因人而异,your mileage may vary),尤其是页面上方的内容。可能会被 Google 扣分,认为这部分内容过多。但不要假设,一定要进行测试!

注意事项

  1. 目前我只在首页这样做,以便让用户更快地渲染出最重要的页面。

  2. CSS 不会被缓存。 但我并不太担心,因为一旦用户进入我的网站的另一个页面,该 .css 文件就会被缓存(见注释1)。


6
感谢你的投入和研究,但我个人不会想去那样做 :D - Niet the Dark Absol
3
那么除了试图达到一个不会真正有所帮助的分数之外,还有什么意义呢? - LarryBud
1
不错,你将你的分数提高了,但现在你网站上的每个页面都会更加重要。不过,这是个好发现。 - EdwardM
@EdwardM 谢谢!请看我在帖子中的注释2。一旦它们到达第二页,CSS就会被缓存,重量问题就会消失。 - elbowlobstercowstand
1
@LarryBud 高分数的意义?对我来说就是更多的钱。我的网站在Google上排名越高,就越有可能被点击并成为客户。因为Google使用页面速度来确定排名,所以我决定提高我的得分。 - elbowlobstercowstand
@NiettheDarkAbsol :) 是的,我听到你了。:| 我并不是很喜欢这样做。但是说到底,更高的排名[对我来说]意味着更多的钱。在这种情况下,我愿意放弃我的编码理念,以满足这个优先级。 - elbowlobstercowstand

9
  • 昨天我看到了这篇有关CSS优化的文章: CSS profiling for ... optimization
    其中包含了很多关于CSS以及哪些CSS会影响性能的有用信息。

  • 我在jQueryUK上看到了有关Google Chrome(Canary)Dev Tools中“隐藏秘密”的演示文稿: DevTools Can do that。 请查看有关Time to First Paint、重绘和代价高昂的CSS的部分。

  • 此外,如果您正在使用像requireJS这样的加载器,您可以查看其中一个CSS加载器插件,称为require-CSS,它使用CSSO - 一种也进行结构优化的优化器,例如合并具有相同属性的块。我用过几次,它可以在不同情况下节省相当多的CSS。

关于问题: 我支持@Enzino创建一个包含所有小图标的sprite。文件大小非常小,不需要为每个图标进行服务器往返。还要记住浏览器可以处理的并发http请求的总数。因此,对于大量小图标的请求也会“阻塞渲染”。虽然与您的页面相比是一个空白页,但我喜欢例如duckduckgo如何加载。


看起来DuckDuckGo也不关心他们的页面得分,可以在这里检查。 - eQ19

6
请查看以下页面https://varvy.com/pagespeed/render-blocking-css.html。这帮助我解决了“渲染阻塞CSS”的问题。我使用了以下代码来移除“渲染阻塞CSS”,现在在谷歌页面速度分析中,我没有遇到与渲染阻塞CSS相关的问题。
<!-- loadCSS -->
<script src="https://cdn.rawgit.com/filamentgroup/loadCSS/6b637fe0/src/cssrelpreload.js"></script>
<script src="https://cdn.rawgit.com/filamentgroup/loadCSS/6b637fe0/src/loadCSS.js"></script>
<script src="https://cdn.rawgit.com/filamentgroup/loadCSS/6b637fe0/src/onloadCSS.js"></script>
<script>
      /*!
      loadCSS: load a CSS file asynchronously.
      */
      function loadCSS(href){
        var ss = window.document.createElement('link'),
            ref = window.document.getElementsByTagName('head')[0];

        ss.rel = 'stylesheet';
        ss.href = href;

        // temporarily, set media to something non-matching to ensure it'll
        // fetch without blocking render
        ss.media = 'only x';

        ref.parentNode.insertBefore(ss, ref);

        setTimeout( function(){
          // set media back to `all` so that the stylesheet applies once it loads
          ss.media = 'all';
        },0);
      }
      loadCSS('styles.css');
    </script>
    <noscript>
      <!-- Let's not assume anything -->
      <link rel="stylesheet" href="styles.css">
    </noscript>

2
当我使用提到的函数时,它会降低页面速度得分。我写的函数是:https://jsfiddle.net/kvfzbxxo/你能帮我解决这个问题吗? - arshovon
我使用了这段代码:https://jsfiddle.net/sbpa1hun/。现在网站中的CSS没有被加载。 - arshovon
1
如果您正在尝试在jsfiddle中执行此操作,则无法正常工作,请尝试在您的网站上使用此代码,因为jsfiddle将阻止加载外部网站的CSS。因为您正在使用JavaScript加载外部来源的CSS。所以请尝试在您的网站上执行此操作。还要尝试包含jQuery文件,它们在您的脚本中缺失。在包含js文件后,这可能会起作用。另请注意,https网站可能在jsfiddle中工作。您正在收到此错误:“已阻止加载混合活动内容”。您需要先解决此问题。 - Amuk Saxena
感谢您撰写有关此问题的博客文章。由于某些原因,combined_css未能加载。基本上,appendAtLast功能无法正常运行。如果我使用loadCss来加载所有三个CSS文件,则将页面速度从44降至39。 - arshovon
显示剩余2条评论

4

我也曾为这个新的页面速度指标苦恼过。

虽然我没有找到实际的方法来将我的得分提高到100%,但还是有一些事情我发现很有帮助。

将所有的CSS文件合并成一个文件,这对我很有帮助。我的所有网站得分都回到了95%至98%。

除此之外,我能想到的就是把必要的CSS(至少对于我的页面来说)全部内联到第一页上,以获得高分。尽管它可能有助于您的速度得分,但这很可能会使您的页面加载速度变慢。


2
Smashing杂志在Pagespeed测试中获得了100%的得分。https://developers.google.com/speed/pagespeed/insights/?url=http%3A%2F%2Fwww.smashingmagazine.com%2F - Mo.

2
2019年的最佳解决方案是HTTP/2服务器推送
您不需要任何hacky JavaScript解决方案或内联样式。但是,您需要支持HTTP 2.0的服务器(任何现代服务器版本都支持),这本身需要您的服务器运行SSL。但是,使用Let's Encrypt没有理由不使用SSL。
我的网站https://r.je/在移动和桌面上都获得了100/100的分数。
这些错误的原因是浏览器获取HTML,然后必须等待CSS下载完成才能呈现页面。使用HTTP2,您可以同时发送HTML和CSS。
您可以通过设置Link头来使用HTTP/2推送。
Apache示例(.htaccess):
Header add Link "</style.css>; as=style; rel=preload, </font.css>; as=style; rel=preload"

对于NGINX,您可以在服务器配置中的location标记中添加头文件:

对于NGINX,您可以在服务器配置中的location标记中添加头文件:

location = / {
    add_header Link "</style.css>; as=style; rel=preload, </font.css>; as=style; rel=preload";
}

设置这个头部信息后,浏览器同时接收到HTML和CSS文件,从而避免了CSS阻塞渲染。你需要进行一些调整,使得CSS只在第一次请求时发送,但Link头部信息是“消除渲染阻塞Javascript和CSS”的最完整、最不破坏性的解决方案。想要了解更详细的讨论,请查看我在此处发布的文章:使用HTTP/2推送消除渲染阻塞CSS

我可能理解有误,但是服务器推送难道不会导致CSS在每次加载页面时都被发送,而不仅仅是在缓存之前发送一次吗? - Niet the Dark Absol
是的,有一些技术,比如cookies可以帮助避免这种情况。请查看有关选择性推送的部分:http://www.nginx.com/blog/nginx-1-13-9-http2-server-push/ - Tom B

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接