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

4

10

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

Garik answered 9/11, 2018 at 5:20 Comment(5)
Do you have an example where FOUC is happening and you don't expect it to?Superdominant
Often the problem is CSS in the HTML body. If the HTML is rendered before the CSS is encountered (because the parsing has stalled), a FOUC will be the result.Catt
@JuanMendes I totally expect FOUC to happen, because my CSS is not downloaded and the render-tree is not created, and the style rendering is stalled. But, as you commented in the answer, my question was why is CSS called to be render blocking?Garik
@Catt Inline CSS would be parser-blocking, if I am right and would not show full content. And I don't think, delay in parsing causes fouc. Delay in parsing should show a blank page. No?Garik
@VishnuSankaran. No. If there's no CSS in the process of being fetched - i.e. the page is not render blocked - the browser will render whatever DOM it has constructed at the point where the parsing stalls.Catt
I
0

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

Impeccant answered 9/11, 2018 at 13:3 Comment(7)
This doesn't explain how the HTML would render before the render blocking CSS is parsed. It seems to misunderstand what render-blocking-css is. The point is that it should not allow FOUCSuperdominant
Sure, in what way does it misunderstand? The DOM can render without the CSSOM. But the Render Tree cannot render until both are constructed.Impeccant
But the article you talked about mentions that it blocks without showing it until it builds the CSSOM. CSS is a render blocking resource. Get it to the client as soon and as quickly as possible to optimize the time to first render. The OP is asking if that's true, why does my CSS not block the render?Superdominant
@Impeccant Thank you. I get this flow. But according to this, CSS is not render-blocking. (yet to go through the video)Garik
Thanks for your comments guys. I would like to explain that 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 :)Impeccant
@Impeccant This explaination sounds plausible. Can you edit your answer to add this? Thanks.Garik
@VishnuSankaran sure. Done.Impeccant
D
7

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.

Decrepitate answered 9/4, 2020 at 13:52 Comment(0)
B
1

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

Breadfruit answered 4/3, 2021 at 15:0 Comment(1)
So it doesn't wait until the whole HTML page is parsed to render/paint the page? That's weird.Washstand
I
0

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

Impeccant answered 9/11, 2018 at 13:3 Comment(7)
This doesn't explain how the HTML would render before the render blocking CSS is parsed. It seems to misunderstand what render-blocking-css is. The point is that it should not allow FOUCSuperdominant
Sure, in what way does it misunderstand? The DOM can render without the CSSOM. But the Render Tree cannot render until both are constructed.Impeccant
But the article you talked about mentions that it blocks without showing it until it builds the CSSOM. CSS is a render blocking resource. Get it to the client as soon and as quickly as possible to optimize the time to first render. The OP is asking if that's true, why does my CSS not block the render?Superdominant
@Impeccant Thank you. I get this flow. But according to this, CSS is not render-blocking. (yet to go through the video)Garik
Thanks for your comments guys. I would like to explain that 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 :)Impeccant
@Impeccant This explaination sounds plausible. Can you edit your answer to add this? Thanks.Garik
@VishnuSankaran sure. Done.Impeccant
A
0

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.

Apart answered 16/3, 2023 at 17:9 Comment(1)
Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.Appomattox

© 2022 - 2024 — McMap. All rights reserved.