Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does CSS blocks rendering?

I'm still unable to understand this concept of "CSS is render-blocking" very clearly. I do understand very well how JS is parser blocking. But, the former is still a little unclear to me.

Let's take an example:

index.html:

<!DOCTYPE html>
<html>
<head>
  <title>Some Document</title>
  <link href='cdn1.com/styles1.css' rel="stylesheet"/>
  <link href='cdn2.com/styles2.css' rel="stylesheet"/>
</head>
<body>
   ...
   ...
</body>
</html>

style1.css (from cdn1):

body { background: blue }

style2.css (from cdn2):

body { background: red }

Now, let's assume style1.css from cdn1 took 1 sec to load whereas style2 from cdn2 took 500ms. I want to know what all things the end-user would see happening in the browser between the following timeline:

  1. at time T < 500ms: Would there be a FOUC or a blank page since CSS is render-blocking and render tree won't construct until we have the styles1.css file
  2. at time 500ms < T < 1sec: Would there be a red page (since style2.css has already loaded), a FOUC or still a blank page for the reason mentioned in point 1.

Also, would the result be consistent on every browser out there, primarily, Edge, Chrome, Firefox and Safari?

like image 772
UtkarshPramodGupta Avatar asked Oct 19 '25 15:10

UtkarshPramodGupta


1 Answers

The following examples uses resources that are deliberately delayed to show what happens. Because it uses dynamic resources to show a different id each time and provide cache-busting, I can't use a stack snippet, but I'll show you the critical code and a link to a working example.

In the first example we have the case you describe.

<!DOCTYPE html>
<html>
<head>
  <title>Render Blocking Test - A</title>
  <link href='/css/styles1.css?delay=1000&x={cachebuster}' rel="stylesheet"/>
  <link href='/css/styles2.css?delay=5000&x={cachebuster}' rel="stylesheet"/>
</head>
<body>
   <h1>Render Blocking Test - A</h1>
   <b>{cachebuster}</b>
</body>
</html>

The placeholder "{cachebuster}" is replaced by a different GUID each refresh. Delays for the two CSS resources are 1 second and 5 seconds to show the delays more clearly

styles1.css contains

body { background: blue }

styles2.css contains

body { background: red }

See it working here: http://alohci.net/text/html/render-blocking-a.htm

You'll see that the page is blank until the 5 seconds have passed, and all the css resources are downloaded. Or on refresh, the previous page remains shown until the 5 seconds have passed (the GUID changes after 5 seconds). The background, when it and the new content appears, is immediately red, not white or blue. This is what render blocking means - no new render of the page is done until the render-blocking resources are available.


For comparison, see this second example.

<!DOCTYPE html>
<html>
<head>
  <title>Render Blocking Test - B</title>
  <link href='/css/styles1.css?delay=1000&x={cachebuster}' rel="stylesheet"/>
</head>
<body>
   <h1>Render Blocking Test - B</h1>
   <b>{cachebuster}</b>
   <script src="/js/script1.js?delay=4000&x={cachebuster}"></script>
   <link href='/css/styles2.css?delay=5000&x={cachebuster}' rel="stylesheet"/>
</body>
</html>

See it working here: http://alohci.net/text/html/render-blocking-b.htm

What we've got here is a single render-blocking resource for one second, then some content - the heading and the GUID - then a script which takes 4 seconds to download and then a second render-blocking resource.

In this case, the text and the blue background appear after 1 second. The script loading parser-blocks, so the second css resource is not yet parsed, and therefore it can't block the rendering. Consequently, the blue background is seen. Then the script loads, the second css resource is parsed, and render-blocks until it too is loaded, at which point the background changes from blue to red.

Finally, you might notice that is only takes 5 seconds for the red background to appear, not 9 seconds as you might imagine. That because the parser can still look ahead when it's parser blocked, recognise that it'll probably need to download the second css resource and pro-actively fetch it, even though it can't use it until the parser unblocks.

like image 101
Alohci Avatar answered Oct 22 '25 06:10

Alohci



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!