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

1.2k views Asked by At

In order to construct the render-tree, the browser requires both DOM and CSSOM. CSSOM can only be constructed, once the CSS is downloaded. In essence, once the CSS is downloaded the page should be rendered alright. But, why do we see Flash Of Unstyled Content(FOUC) on the page? In what time window does the browser show unstyled content?

Please help me understand this.

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

4

There are 4 answers

7
jburtondev On BEST ANSWER

This should help.

  1. DOM is constructed
  2. If we are still waiting for the CSSOM to be constructed, then we see FOUC
  3. CSSOM is constructed
  4. DOM and CSSOM are coalesced into the Render Tree which renders the DOM with CSS (styled content)

So the browser shows FOUC when waiting for CSS. Once the CSS is loaded, the DOM and CSSOM are merged into one tree, called the Render Tree and this is styled content.

The very fact that HTML is rendered unstyled is clear evidence that the HTML can render in the browser separately from the render tree, thus causing FOUC.

According to the Google article, the NY times site shows FOUC until the CSSOM is constructed and then the render tree is rendered. This demonstrates that rendering the render tree is different from rendering the DOM tree. The DOM tree is rendered, but unloaded CSS blocks the render tree from being rendered (note the difference). This is why the FOUC shows before the CSS is unblocked and the render tree shows.

In my opinion, this is the most comprehensive talk about this subject out there, from David Baron, Chief Engineer at Mozilla: https://vimeo.com/103108124

0
Staneque On

I still don’t agree with the accepted answer, because according to the critical rendering path nothing could be painted on a screen under normal circumstances until the render tree (DOM + CSSOM) is build.

I find that this Google article is somewhat confusing at the first glance but it becomes less contradictory if we take a look carefully at the following statement:

“What would happen if we try to render a typical page without blocking rendering on CSS?”. (Then NY Times FOUC as example of behaviour without blocking rendering follows.)

The thing is historically FOUC happened for different reasons in different browsers versions and on different circumstances.

For example according to this ancient article we could encounter FOUC in web kit if some JS attempted to access properties that have layout/style information.

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.

Therefore when we say “FOUC happens” there should be explications on what circumstances and in what browser it happens, because it doesn’t “just” happens everywhere.

1
Rohit Garg On

The basic reason for FOUC is -> new/different styles are getting applied after elements were already painted on screen.

Now comes the question -> can FOUC happens when page is loading and page markup itself includes <link> tag for external css, at high level it appears this should not happen as css is render blocking and there should be no case where any element can get rendered without its computed styles, but it(FOUC) happens on page load in certain conditions.

Main reason for that is dom tree construction is incremental i.e. without having the full html markup browser can render partial html whatever is downloaded till the given point of time.

To understand that lets take example of following 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. First 100 tags are converted to dom and with help of existing cssom(which was construed from user agent stylesheets) forms render tree, which will be painted and will be visible to user.
  2. After that parsing will be blocked till css1 is downloaded and new cssom is created with useragent+css1 styles.
  3. And with new render tree(formed via old dom + new cssom) html block 1 will be updated(FOUC)
  4. Then html block 2 is similarly processed as it gets downloaded after that.
  5. Now same things as step 3 is repeated with block 2 and block 3
  6. And same goes on till the end of document

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

1
coding抠腚 On

You need to carefully read the article:

The above example, showing the NYTimes website with and without CSS, demonstrates why rendering is blocked until CSS is available---without CSS the page is relatively unusable

The screenshot is not what actually happens in browsers, it's there to demonstrate what would happen if CSS was not render-blocking. Your original understanding is correct, FOUC is not possible under normal circumstances. However, if you apply additional styles later in the page or via Javascript, you need to make sure they're injected before any HTML affected by those styles to prevent FOUC.