css影响渲染

tech2022-09-14  103

css影响渲染

This article is part of a series created in partnership with SiteGround. Thank you for supporting the partners who make SitePoint possible.

本文是与SiteGround合作创建的系列文章的一部分。 感谢您支持使SitePoint成为可能的合作伙伴。

I’ve always thought deciding how and when to load CSS files is something best left to browsers. They handle this sort of thing by design. Why should developers do anything more than slap a link element with rel="stylesheet" and href="style.css" inside the <head> section of the document and forget about it?

我一直认为,决定如何以及何时加载CSS文件是浏览器最好的选择。 他们通过设计来处理这种事情。 为什么开发人员除了在文档的<head>部分内使用rel="stylesheet"和href="style.css"链接元素之外,还要做什么呢?

Apparently, this may not be enough today, at least if you care about website speed and fast-rendering webpages. Given how both these factors impact on user experience and the success of your website, it’s likely you’ve been looking into ways you can gain some control over the default way in which browsers deal with downloading stylesheets.

显然,今天这可能还不够,至少在您关心网站速度和快速呈现网页的情况下。 考虑到这两个因素如何影响用户体验和网站的成功,您可能一直在寻找可以对浏览器处理样式表下载的默认方式进行某种控制的方法。

In this article, I’m going to touch on what could be wrong with the way browsers load CSS files and discuss possible ways of approaching the problem, which you can try out in your own website.

在本文中,我将探讨浏览器加载CSS文件的方式可能出了什么问题,并讨论解决该问题的可能方法,您可以在自己的网站中进行尝试。

问题:CSS正在渲染阻塞 (The Problem: CSS Is Render Blocking)

If you’ve ever used Google Page Speed Insights to test website performance, you might have come across a message like this:

如果您曾经使用Google Page Speed Insights来测试网站的性能,则可能会遇到以下消息:

Here Google Page Insights is stating the problem and offering a strategy to counteract it.

Google Page Insights在此说明了问题并提供了解决问题的策略。

Let’s try to understand the problem a bit better first.

让我们首先尝试更好地理解问题。

Browsers use the DOM (Document Object Model) and the CSSOM (CSS Object Model) to display web pages. The DOM is a model of the HTML which the browser needs in order to be able to render the web page’s structure and content. The CSSOM is a map of the CSS, which the browser uses to style the web page.

浏览器使用DOM(文档对象模型)和CSSOM(CSS对象模型)来显示网页。 DOM是浏览器需要HTML模型,以便能够呈现网页的结构和内容。 CSSOM是CSS的地图,浏览器使用CSS样式设置网页样式。

CSS being on the critical rendering path means that the browser stops rendering the web page until all the HTML and style information is downloaded and processed. This explains why both HTML and CSS files are considered to be render blocking. External stylesheets especially involve multiple roundtrips between browser and server. This may cause a delay between the time the HTML has been downloaded and the time the page renders on the screen.

CSS位于关键渲染路径上, 这意味着浏览器将停止渲染网页,直到下载并处理所有HTML和样式信息为止。 这就解释了为什么HTML和CSS文件都被认为是阻止渲染的 。 外部样式表尤其涉及浏览器和服务器之间的多次往返。 这可能会导致HTML下载时间和页面在屏幕上呈现时间之间的延迟。

The problem consists in this delay, during which users could be staring at a blank screen for a number of milliseconds. Not the best experience when first landing on a website.

问题在于这种延迟,在此期间用户可能凝视空白屏幕数毫秒。 初次登陆网站不是最佳体验。

关键CSS的概念 (The Concept of Critical CSS)

Although HTML is essential to page rendering, otherwise there would be nothing to render, can we say the same about CSS?

尽管HTML是页面呈现所必需的,否则将无法呈现任何内容,关于CSS我们能说同样的话吗?

Of course, an unstyled web page is not user friendly, and from this point of view it makes sense for the browser to wait until the CSS is downloaded and parsed before rendering the page. On the other hand, you could argue that not all style information is critical to building a usable page. What users are immediately interested in is the above the fold portion of the page, that is, that portion which users can consume without needing to scroll.

当然,没有样式的网页不是用户友好的,从这个角度来看,对于浏览器来说,在呈现页面之前,要等到CSS的下载和解析之后才有意义。 另一方面,您可能会争论并非所有样式信息对于构建可用页面都是至关重要的 。 用户立即感兴趣的是页面折叠部分的上方 ,即用户无需滚动即可使用的部分。

This thought is behind the dominant approach available today to solve this problem, including the suggestion contained in the message from Google Page Insights reported above. The bit of interest there reads:

这种想法是当今解决该问题的主流方法的背后,包括上面报道的Google Page Insights消息中所包含的建议。 有趣的地方是:

Try to defer or asynchronously load blocking resources, or inline the critical portions of those resources directly in the HTML.

尝试延迟或异步加载阻塞资源,或直接在HTML中内联这些资源的关键部分。

But how do you defer or asynchronously load stylesheets on your website?

但是,如何延迟或异步加载网站上的样式表?

Not as straightforward as it might sound. You can’t just toss an async attribute on the link element as if it were a <script> tag.

没有听起来那么简单。 您不能只将link元素上的async属性扔掉,就好像它是<script>标签一样。

Below are a few ways in which developers have tackled the problem.

以下是开发人员解决该问题的几种方法。

利用媒体类型和媒体查询来最大程度地减少渲染阻塞 (Take Advantage of Media Types and Media Queries to Minimize Render Blocking)

Ilya Grigorik illustrates a simple way of minimizing page rendering block which involves two stages:

Ilya Grigorik演示了一种最小化页面呈现块的简单方法,该过程涉及两个阶段:

Split the content of your external CSS into different files according to media type and media queries, thereby avoiding big CSS documents that take longer to download

根据媒体类型和媒体查询将外部CSS的内容拆分为不同的文件,从而避免下载花费较长时间的大型CSS文档 Reference each file with the appropriate media type and media query inside the link element. Doing so prevents some stylesheet files from being render blocking if the conditions set out by the media type or media query are not met.

在link元素内使用适当的媒体类型和媒体查询引用每个文件。 如果不满足由媒体类型或媒体查询设置的条件,这样做可以防止某些样式表文件被渲染阻止。

As an example, references to your external CSS files in the <head> section of your document might look something like this:

例如,在文档的<head>部分中对外部CSS文件的引用可能类似于以下内容:

<link href="style.css" rel="stylesheet"> <link href="print.css" rel="stylesheet" media="print"> <link href="other.css" rel="stylesheet" media="(min-width: 40em)">

The first link in the snippet above doesn’t use any media type or media query. The browser considers it as matching all cases, therefore it always delays page rendering while fetching and processing the resource.

上面代码段中的第一个链接不使用任何媒体类型或媒体查询。 浏览器认为它适合所有情况,因此在获取和处理资源时总是会延迟页面渲染。

The second link has a media="print" attribute, which is a way of telling the browser: “Howdy browser, make sure you apply this stylesheet only if the page is being printed”. In the context of the page simply being viewed on the screen, the browser knows that stylesheet is not needed, therefore it won’t block page rendering to download it.

第二个链接具有media="print"属性,它是一种告诉浏览器的方式:“ Howdy浏览器,请确保仅在打印页面时才应用此样式表”。 在仅在屏幕上查看页面的上下文中,浏览器知道不需要样式表,因此它不会阻止页面渲染来下载它。

Finally, the third link contains media="(min-width: 40em)", which means that the stylesheet being referenced in the link is render-blocking only if the conditions stated by the media query match, i.e., where the viewport’s width is at least 40em. In all other cases the resource is not render blocking.

最后,第三个链接包含media="(min-width: 40em)" ,这意味着仅当媒体查询所指定的条件匹配时(即视口的宽度为至少40em。 在所有其他情况下,资源不会被阻塞。

Also, take note that the browser will always download all stylesheets, but will give lower priority to non-blocking ones.

另外,请注意,浏览器将始终下载所有样式表,但对非阻塞样式表的优先级较低。

To sum up, this approach doesn’t completely eliminate the problem, but can considerably minimize the time browsers block page rendering.

综上所述,这种方法不能完全消除问题,但是可以大大减少浏览器阻止页面渲染的时间。

在链接元素上使用预加载指令 (Using the preload Directive on the Link Element)

A cutting-edge feature you could leverage to counteract the block of the web page by browsers as they fetch external stylesheets, is the standard-based preload directive.

基于浏览器在获取外部样式表时可以利用的最先进功能来抵消网页的阻塞,这是基于标准的preload指令 。

preload is how we, as developers, can tell browsers to fetch specific resources because we know the page is going to need those resources quite soon.

preload是我们作为开发人员可以告诉浏览器获取特定资源的方式,因为我们知道页面很快就会需要这些资源。

Scott Jehl, designer and developer working for The Filament Group, can be credited to be the first one who tinkered with this idea.

The Filament Group的设计师和开发人员Scott Jehl可以说是第一个对此想法进行修改的人 。

Here’s what you need to do.

这是您需要做的。

Add preload to the link referencing the stylesheet, add a tiny bit of JavaScript magic using the link’s onload event, and the result is like having an asynchronous loading of the stylesheet directly in your markup:

将preload添加到引用样式表的链接中,使用链接的onload事件添加一点JavaScript魔术,其结果就像是直接在标记中异步加载样式表:

<link rel="preload" as="style" href="style.css" onload="this.rel='stylesheet'">

The snippet above gets the browser to fetch style.css in a non-blocking way. After the resource has finished loading, i.e., the link’s onload event has fired, the script replaces the preload value of the rel attribute with stylesheet and the styles are applied to the page.

上面的代码段使浏览器以非阻塞方式获取style.css 。 资源完成加载后,即,激发了链接的onload事件后,脚本将rel属性的preload值替换为stylesheet ,并将样式应用于页面。

At this time browser support for preload is confined to Chrome and Opera. But fear not, a polyfill provided by the Filament Group is at hand.

目前, 浏览器对preload支持仅限于Chrome和Opera。 但是不要担心,Filament Group提供的填充料就在眼前。

More on this in the next section.

下一节将对此进行更多介绍。

Filament Group的解决方案:从内联CSS到HTTP / 2服务器推送 (The Filament Group’s Solution: From Inlining CSS to HTTP/2 Server Push)

Solving the problem of delayed page rendering due to fetching of critical resources has long been the highest priority for the Filament Group, an award-winning design and development agency based in Boston:

长期以来,解决因获取关键资源而导致页面渲染延迟的问题一直是Filament Group的头等大事。FilamentGroup是一家屡获殊荣的设计和开发机构,总部位于波士顿:

Our highest priority in the delivery process is to serve HTML that’s ready to begin rendering immediately upon arrival in the browser.

在交付过程中,我们最优先考虑的是提供HTML,这些HTML准备在到达浏览器后立即开始呈现。

The latest update on optimizing web page delivery outlines their progress from inlining critical CSS to super efficient HTTP/2 Server Push.

有关优化网页交付的最新更新概述了它们从内联关键CSS到超高效HTTP / 2 Server Push的进展。

The overall strategy looks like this:

总体策略如下:

Any assets that are critical to rendering the first screenful of our page should be included in the HTML response from the server.

服务器HTML响应中应包含任何对于呈现页面的第一屏至关重要的资产。 Any assets that are not critical to that first rendering should be delivered in a non-blocking, asynchronous manner.

对于第一次渲染而言并不重要的任何资产,都应以非阻塞,异步的方式交付。

Before HTTP/2 Server Push, implementing #1 consisted in selecting the critical CSS rules, i.e., those needed for default styles and for a seamless rendering of the above the fold portion of the webpage, and cramming them in a <style> element inside the page’s <head> section. Filament Group devs devised Critical, a cool JavaScript plugin, to automate the task of extracting critical CSS.

在HTTP / 2 Server Push之前,实现#1的方法是选择关键CSS规则,即默认样式以及网页的折叠部分上方的无缝呈现所需的规则,然后将其塞入内部的<style>元素中页面的<head>部分。 Filament Group开发人员设计了Critical (一个很酷JavaScript插件)来自动化提取关键CSS的任务。

With recent adoption of HTTP/2 Server Push, Filament Group has moved beyond inlining critical CSS.

随着最近采用HTTP / 2 Server Push,Filament Group已经超越了内联关键CSS的范围。

What is Server Push? What is it good for?

什么是服务器推送? 到底有什么好处呢?

Server push allows you to send site assets to the user before they’ve even asked for them. …

服务器推送允许您在用户要求站点资产之前就将其发送给用户。 …

Server push lets the server preemptively “push” website assets to the client without the user having explicitly asked for them. When used with care, we can send what we know the user is going to need for the page they’re requesting.

服务器推送使服务器可以抢先将网站资产“推送”到客户端,而无需用户明确要求。 当谨慎使用时,我们可以发送我们知道用户将为其请求的页面所需的信息。

Jeremy Wagner

杰里米·瓦格纳

In other words, when the browser requests a particular page, let’s say index.html, all the assets that page depends upon will be included in the response, e.g., style.css, main.js, etc., with a huge optimization boost on page rendering speed.

换句话说,当浏览器请求一个特定的页面时,例如index.html ,该页面所依赖的所有资产都将包含在响应中,例如style.css , main.js等,从而极大地提高了优化效率页面渲染速度。

Putting into practice #2, asynchronous loading of non critical CSS, is done using a combination of the preload directive technique discussed in the previous section and LoadCSS, a Filament Group’s JavaScript library that includes a polyfill for those browsers that don’t support preload.

在实践2中,非关键CSS的异步加载是通过结合上一节中讨论的preload指令技术和LoadCSS来完成的 , LoadCSS是Filament GroupJavaScript库,其中包括用于不支持preload浏览器的polyfill 。

Using LoadCSS involves adding this snippet to your document’s <head> section:

使用LoadCSS涉及将此片段添加到文档的<head>部分:

<link rel="preload" href="mystylesheet.css" as="style" onload="this.rel='stylesheet'"> <!-- for browsers without JavaScript enabled --> <noscript><link rel="stylesheet" href="mystylesheet.css"> </noscript>

Notice the <noscript> block that references the stylesheet file as usual to cater for those situations when JavaScript goes wrong or has been disabled.

请注意,照常引用样式表文件的<noscript>块可以解决JavaScript错误或已被禁用的情况。

Below the <noscript> tag, include LoadCSS and the LoadCSS rel=preload polyfill script inside a <script> tag:

在<noscript>标记下方,在<script>标记内包含LoadCSS和LoadCSS rel = preload polyfill <script> :

<script> /*! loadCSS. [c]2017 Filament Group, Inc. MIT License */ (function(){ ... }()); /*! loadCSS rel=preload polyfill. [c]2017 Filament Group, Inc. MIT License */ (function(){ ... }()); </script>

You can find detailed instructions on using LoadCSS in the project’s GitHub repo and see it in action in this live demo.

您可以在项目的GitHub存储库中找到有关使用LoadCSS的详细说明,并在此实时演示中进行实际操作。

I lean towards this approach: it’s got a progressive enhancement outlook, it’s clean and developer friendly.

我倾向于这种方法:它具有逐步增强的前景,它干净而且对开发人员友好。

在文档正文中放置指向样式表文件的链接 (Placing the Link to the Stylesheet Files in the Document Body)

According to Jake Archibald, one drawback of the previous approach is that it relies on a major assumption about what you or I can consider as being critical CSS. It should be obvious that all styles applied to the above the fold portion of the page are critical. However, what exactly constitutes above the fold is all but obvious because changes with viewport dimensions affect the amount of content users can access without scrolling. Therefore, one-size-fits-all is not always a reliable guess.

根据Jake Archibald的说法,先前方法的一个缺点是它依赖于关于您或我认为是关键CSS的主要假设。 显而易见,应用于页面折叠部分上方的所有样式都是至关重要的。 但是,折叠上方的确切位置几乎是显而易见的,因为视口尺寸的变化会影响用户无需滚动即可访问的内容量。 因此,“一刀切”并非总是可靠的猜测。

Jake Archibald proposes a different solution, which looks like this:

杰克·阿奇博尔德(Jake Archibald)提出了另一种解决方案 ,如下所示:

<head> </head> <body> <!-- HTTP/2 push this resource, or inline it --> <link rel="stylesheet" href="/site-header.css"> <header>…</header> <link rel="stylesheet" href="/article.css"> <main>…</main> <link rel="stylesheet" href="/comment.css"> <section class="comments">…</section> <link rel="stylesheet" href="/about-me.css"> <section class="about-me">…</section> <link rel="stylesheet" href="/site-footer.css"> <footer>…</footer> </body>

As you can see, references to external stylesheets are not placed in the <head> section but inside the document’s <body>.

如您所见,对外部样式表的引用未放置在<head>部分中,而是在文档的<body> 。

Further, the only styles that are rendered immediately with the page, either inlined or using HTTP/2 Server Push, are those that apply to the upper portion of the page. All other external stylesheets are placed just before the chunk of HTML content to which they apply: article.css before <main>, site-footer.css before <footer>, etc.

此外,内联或使用HTTP / 2 Server Push随页面立即呈现的唯一样式是应用于页面上部的样式。 所有其他外部样式表都放置在它们所应用HTML内容的紧前面: article.css在<main>之前, site-footer.css在<footer>之前,等等。

Here’s what this technique aims to achieve:

这是此技术旨在实现的目的:

The plan is for each <link rel=”stylesheet”/> to block rendering of subsequent content while the stylesheet loads, but allow the rendering of content before it. The stylesheets load in parallel, but they apply in series.

该计划适用于每个<link rel =” stylesheet” />,以在加载样式表时阻止后续内容的呈现,但允许在其之前呈现内容。 样式表是并行加载的,但是它们是串行应用的。

… This gives you a sequential render of the page. You don’t need decide what’s “above the fold”, just include a page component’s CSS just before the first instance of the component.

…这使您可以顺序显示页面。 您无需确定“折中”是什么,只需在该组件的第一个实例之前添加页面组件CSS。

All browsers seem to allow the placement of <link> tags in the document’s <body>, although not all of them behave exactly in the same way. That said, for the most part this technique achieves its goal.

所有浏览器似乎都允许在文档的<body>放置<link>标记,尽管并非所有浏览器的行为都完全相同。 就是说,这种技术在很大程度上实现了其目标。

You can find out all the details on Jake Archibald’s post and check out the result in this live demo.

您可以在Jake Archibald的帖子中找到所有详细信息,并在此现场演示中查看结果。

结论 (Conclusion)

The problem with the way in which browsers download stylesheets is that page rendering is blocked until all files have been fetched. This means user experience when first landing on a web page might suffer, especially for those on flaky internet connections.

浏览器下载样式表的方式的问题在于,在所有文件都被提取之前,页面呈现被阻止。 这意味着首次登陆网页时的用户体验可能会受到影响,尤其是对于那些不稳定的Internet连接的用户。

Here I’ve presented a few approaches that aim to solve this problem. I’m not sure if small websites with relatively little and well-structured CSS would be much worse off if they just left the browser to its own devices when downloading stylesheets.

在这里,我介绍了一些旨在解决此问题的方法。 我不确定如果CSS相对较少且结构良好的小型网站在下载样式表时只是将浏览器留在自己的设备上,情况是否会更糟。

What do you think, does lazy loading stylesheets, or their sequential application (Jake Archibald’s proposal), work as a way of improving page rendering speed on your website? What is the technique you find most effective?

您如何看待,延迟加载样式表或其顺序应用程序(Jake Archibald的建议)可作为提高网站上页面渲染速度的一种方法? 您发现最有效的技术是什么?

Hit the comment box below to share

点击下面的评论框分享

翻译自: https://www.sitepoint.com/critical-rendering-path-css-fast-loading-website/

css影响渲染

最新回复(0)