阻塞渲染的 CSS

Ilya Grigorik
Ilya Grigorik

Published: March 31, 2014

默认情况下,CSS 被视为会阻塞渲染的资源,这意味着浏览器在构建 CSSOM 之前不会渲染任何已处理的内容。请务必保持 CSS 的简洁性,尽快交付 CSS,并使用媒体类型和查询来解除渲染阻塞。

渲染树构建 中,我们看到关键渲染路径需要 DOM 和 CSSOM 才能构建渲染树。这会产生重要的性能影响:HTML 和 CSS 都是会阻塞渲染的资源。HTML 显而易见,因为如果没有 DOM,我们就无法渲染任何内容,但 CSS 要求可能不太明显。如果我们尝试在不阻塞 CSS 渲染的情况下渲染典型网页,会发生什么情况?

摘要

  • 默认情况下,CSS 被视为会阻塞渲染的资源。
  • 借助媒体类型和媒体查询,我们可以将一些 CSS 资源标记为不会阻塞渲染。
  • 无论 CSS 资源是否会阻塞渲染,浏览器都会下载所有 CSS 资源。
包含 CSS 的《纽约时报》移动版网页
不包含 CSS 的《纽约时报》移动版网页 (FOUC)

上一个示例展示了包含和不包含 CSS 的《纽约时报》网站,说明了为什么在 CSS 可用之前渲染会被阻塞:如果没有 CSS,网页相对来说无法使用。右侧的体验通常称为“无样式内容闪烁”(FOUC)。浏览器会阻塞渲染,直到同时拥有 DOM 和 CSSOM。

CSS 是一种会阻塞渲染的资源。请尽快将其交付给客户端,以优化首次渲染时间。

但是,如果我们有一些 CSS 样式仅在特定条件下使用,例如在打印网页或将网页投影到大型显示器上时,该怎么办?如果我们不必阻塞这些资源的渲染,那就太好了。

借助 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)" />

一个 媒体查询 由媒体类型和零个或多个表达式组成,这些表达式用于检查特定媒体功能的条件。例如,我们的第一个样式表声明未提供媒体类型或查询,因此它适用于所有情况;也就是说,它始终会阻塞渲染。另一方面,第二个样式表声明仅在打印内容时适用,也许您希望重新排列布局、更改字体以及其他重要的打印设计注意事项。因此,此样式表声明无需在首次加载网页时阻塞网页的渲染。最后,最后一个样式表声明提供了一个“媒体查询”,该查询由浏览器执行:如果条件匹配,浏览器会阻塞渲染,直到样式表下载并处理完毕。

通过使用媒体查询,我们可以针对特定用例(例如显示与打印)以及动态条件(例如屏幕方向变化、调整大小事件等)定制演示文稿。在声明样式表资源时,请密切关注媒体类型和查询;它们会极大地影响关键渲染路径性能。

请考虑以下示例:

<link href="style.css" rel="stylesheet" />
<link href="style.css" rel="stylesheet" media="all" />
<link href="portrait.css" rel="stylesheet" media="orientation:portrait" />
<link href="print.css" rel="stylesheet" media="print" />
  • 第一个声明会阻塞渲染,并且在所有条件下都匹配。
  • 第二个声明也会阻塞渲染:"all" 是默认类型,因此如果您未指定类型,系统会隐式将其设置为 "all"。因此,第一个声明和第二个声明实际上是等效的。
  • 第三个声明具有动态媒体查询,该查询会在网页加载时进行评估。根据网页加载时设备的屏幕方向,portrait.css 可能会阻塞渲染,也可能不会阻塞渲染。
  • 最后一个声明仅在打印网页时 ("print") 应用,因此在浏览器中首次加载网页时不会阻塞渲染。

最后,请注意,“阻塞渲染”仅指浏览器是否必须在该资源上保留网页的初始渲染。无论哪种情况,浏览器仍会下载 CSS 资源,但对于不会阻塞渲染的资源,其优先级较低。

反馈