如果 CSS 是渲染阻塞,为什么我们会看到 FOUC?

If CSS is render-blocking, why do we see FOUC?

为了构建渲染树,浏览器需要 DOM 和 CSSOM。 CSSOM 只能在 CSS 下载后构建。本质上,一旦 CSS 下载完毕,页面应该可以正确呈现。但是,为什么我们会在页面上看到 Flash Of Unstyled Content(FOUC)?什么时候 window 浏览器会显示无样式的内容?

请帮助我理解这一点。

参考: https://developers.google.com/web/fundamentals/performance/critical-rendering-path/render-blocking-css

这应该有所帮助。

  1. DOM构造
  2. 如果我们还在等待构建CSSOM,那么我们会看到FOUC
  3. CSSOM构建
  4. DOM 和 CSSOM 合并到渲染树中,用 CSS(样式化内容)
  5. 渲染 DOM

因此浏览器在等待CSS时显示FOUC。加载 CSS 后,DOM 和 CSSOM 合并为一棵树,称为渲染树,这是样式化的内容。

HTML 呈现无样式这一事实清楚地证明 HTML 可以在浏览器中与呈现树分开呈现,从而导致 FOUC。

根据Google文章,纽约时报网站显示FOUC,直到构建CSSOM,然后渲染树。这表明渲染渲染树不同于渲染 DOM 树。 DOM 树被渲染,但卸载 CSS 阻止渲染树被渲染(注意区别)。这就是为什么 FOUC 在 CSS 解锁和渲染树显示之前显示的原因。

在我看来,这是关于这个主题的最全面的演讲,来自 Mozilla 的首席工程师 David Baron:https://vimeo.com/103108124

我仍然不同意接受的答案,因为根据关键渲染路径,在渲染树 (DOM + CSSOM 之前,正常情况下无法在屏幕上绘制任何内容) 正在构建。

我发现这篇 Google 文章乍一看有点令人困惑,但如果我们仔细看一下以下陈述,就会发现矛盾会减少:

“如果我们尝试在 CSS 上呈现典型页面 而不阻塞呈现 会发生什么?”。 (然后纽约时报 FOUC 作为行为示例 不阻塞渲染 如下。)

从历史上看,FOUC 在不同浏览器版本和不同情况下因不同原因而发生。

例如,根据 this ancient article,如果某些 JS 试图访问具有 layout/style 信息的属性,我们可能会在 web kit 中遇到 FOUC。

Web Kit has the opposite behavior and will continue parsing a page even after a style sheet directive has been encountered so that style sheet and script loads can be parallelized. That way everything can be ready for display much earlier.

The problem with this behavior is what to do when a script attempts to access a property that involves having accurate layout/style information to answer. Shipping Safari’s current behavior when this happens is as follows: it will go ahead and lay out what it’s got even though it doesn’t have the style sheet yet. It will also display it. This means you see FOUC whenever a script tries to access properties like scrollHeight or offsetWidth before the style sheet has loaded.

因此,当我们说“FOUC发生”时,应该对 它发生在什么情况下以及在什么浏览器中,因为它没有 “只是”无处不在。

FOUC 的基本原因是 -> new/different 在屏幕上绘制元素后应用样式。

现在问题来了 -> FOUC 是否会在页面加载时发生,并且页面标记本身包含 <link> 外部标签 css,在高层看来这不应该发生,因为 css 是渲染阻塞,应该没有任何元素可以在没有其计算样式的情况下渲染的情况,但它(FOUC)在某些条件下发生在页面加载时。

主要原因是 dom 树构建是渐进的,即没有完整的 html 标记浏览器可以呈现部分 html 在给定时间点之前下载的任何内容。

为了理解让我们以下面的例子为例 html -

<!DOCTYPE html>
<html lang="en">
  <body>
    <100 html tags block 1 />
    <link href="css1" />
    <100 html tags block 2 />
    <link href="css2" />
    <100 html tags block 3 />
    <link href="css3" />
  </body>
</html>
  1. 前 100 个标签被转换为 dom 并在现有的 cssom(从用户代理样式表中解释)的帮助下形成渲染树,这将被绘制并且对用户可见.
  2. 之后解析将被阻止,直到下载 css1 并使用 useragent+css1 样式创建新的 cssom。
  3. 并使用新渲染树(通过旧 dom + 新 cssom 形成)html 块 1 将被更新(FOUC)
  4. 然后 html 块 2 被类似地处理,因为它在那之后被下载。
  5. 现在在块 2 和块 3 中重复与步骤 3 相同的事情
  6. 同样的操作直到文件结束

学分 - https://medium.com/jspoint/how-the-browser-renders-a-web-page-dom-cssom-and-rendering-df10531c9969