默认情况下,CSS 被视为阻塞渲染的资源,这意味着浏览器不会渲染任何已处理的内容,直到 CSSOM 构建完毕。请务必精简您的 CSS,尽快提供它,并使用媒体类型和查询来恢复呈现。
在渲染树构建中,我们看到关键渲染路径需要 DOM 和 CSSOM 才能构建渲染树。这会对性能产生重大影响:HTML 和 CSS 都是阻塞渲染的资源。HTML 是显而易见的,如果没有 DOM,我们将没有任何可呈现的内容,但 CSS 的要求可能就不那么明显了。如果我们尝试在不阻止 CSS 上渲染的情况下渲染普通网页,会发生什么情况?
摘要
- 默认情况下,CSS 被视为阻塞渲染的资源。
- 通过媒体类型和媒体查询,我们可以将一些 CSS 资源标记为不阻塞渲染。
- 浏览器会下载所有 CSS 资源(无论阻塞行为还是非阻塞行为)。
![纽约时报与 CSS](https://web.developers.google.cn/static/articles/critical-rendering-path/render-blocking-css/image/nytimes-css-de9a8a85f18fa.png?authuser=6&hl=hu)
![不使用 CSS 的纽约时报](https://web.developers.google.cn/static/articles/critical-rendering-path/render-blocking-css/image/nytimes-without-css-6d823cc9c8ea4.png?authuser=6&hl=hu)
上例展示了纽约时报网站使用和不使用 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 可能阻塞渲染,也可能不阻塞渲染。
- 最后一个声明仅在打印网页时应用,因此网页首次在浏览器中加载时,它不会阻塞渲染。
最后请注意,“阻塞渲染”仅是指浏览器是否必须暂停该资源上网页的初始渲染。无论哪种情况,浏览器仍会下载 CSS 资源,只是非阻塞资源的优先级较低。