The article says CSS is render blocking so js will evaluate after building a CSSOM(a.k.a. recalculating style in dev tools)
But, in Chrome dev tools. It seems js is evaluated before CSSOM why is it? Did I misunderstand it?
If you want to see my example => here
Call Tree
Event log
<html>
<head>
<style>
h1 {color:red;}
p>p {color:blue;}
p>p>p {color:blue;}
p>p>p>p {color:blue;}
p>p>p>p>p {color:blue;}
p>p>p>p>p>p {color:blue;}
p>p>p>p>p>p>p {color:blue;}
p>p>P>p>p>p>p>p {color:blue;}
</style>
</head>
<body>
<h1>A heading</h1>
<p>A paragraph.</p>
<p>Hello <span>web performance</span> students!</p>
<div><img src="awesome-photo.jpg"></div>
<script>
var span = document.getElementsByTagName('span')[0];
span.textContent = 'interactive'; // change DOM text content
span.style.display = 'inline'; // change CSSOM property
// create a new element, style it, and append it to the DOM
var loadTime = document.createElement('div');
loadTime.textContent = 'You loaded this page on: ' + new Date();
loadTime.style.color = 'blue';
document.body.appendChild(loadTime);
var cnt=0
while(cnt++ <=9999999){}
</script>
</body>
</html>
Changing the DOM, through adding and removing elements, changing attributes, classes, or through animation, will all cause the browser to recalculate element styles and, in many cases, layout (or reflow) the page, or parts of it. This process is called computed style calculation.
The “Computed” tab is generally located in the right panel of the DevTools interface, like it is shown here in Chrome. The content in the Computed tab is important because it shows us the values that the browser is actually using on the rendered website.
The author of the article is focusing on the domContentLoaded
event or as in the moment when the page is ready to be present to the user, no more white screen. When the blue vertical line appears in the timeline matters. This is an important event to understand how quickly the page is available to the user. How long does the user have to stare at the white screen before the content is present?
Due to the advent of single-page applications, almost all of the content is only available after the main scripts load. This is why so many of the top web application uses server-side rendered pages delivered first then the javascript take control of the single page application. They even employ code-splitting to load just what is needed on the current page.
The article dives into the effects of including external CSS and js files. How the loading and parsing of these files can push the domContentLoaded
event, meaning more delays in changing that white screen to content, even though the content (HTML) is already parsed and ready to be presented.
The performance event log does show details of what is happening, but if you scroll down further, you can find the Event:readystatechange
and Event:pageshow
, representing the timestamp of when the content is presented to the user. These events are after the script and style computation. The <script>
line blocks the domContentLoaded
event until he can finish his things.
This is why it's recommended to use the async
attribute to the script tag so that it doesn't block the white screen. Imagine if all the external scripts that we add to our webpage also block the page rendering. The delay will become so apparent to the user that he/she may decide to leave.
Hope this explains your query.
I think there are some optimizations when you have inline or parser blocking script in Chrome and IE11
When I tested below HTML
<html>
<head>
<style>
h1 {color:red;}
p>p {color:blue;}
p>p>p {color:blue;}
p>p>p>p {color:blue;}
p>p>p>p>p {color:blue;}
p>p>p>p>p>p {color:blue;}
p>p>p>p>p>p>p {color:blue;}
p>p>P>p>p>p>p>p {color:blue;}
</style>
</head>
<body>
<h1>A heading</h1>
<p>A paragraph.</p>
<p>Hello <span>web performance</span> students!</p>
<div><img src="awesome-photo.jpg"></div>
<script>
var span = document.getElementsByTagName('span')[0];
span.textContent = 'interactive'; // change DOM text content
span.style.display = 'inline'; // change CSSOM property
// create a new element, style it, and append it to the DOM
var loadTime = document.createElement('div');
loadTime.textContent = 'You loaded this page on: ' + new Date();
loadTime.style.color = 'blue';
document.body.appendChild(loadTime);
var cnt=0
while(cnt++ <=9999999){}
</script>
</body>
</html>
IE11 shows expected order, but executed in parallel. HTML Parsing => CSSOM => evaluate script
The other hand, Chrome shows unexpected order HTML Parsing => evalute script => CSSOM
So I changed inline script to external, now Chrome works as expected order HTML Parsing => CSSOM => evaluate script
<html>
<head>
<style>
h1 {color:red;}
p>p {color:blue;}
p>p>p {color:blue;}
p>p>p>p {color:blue;}
p>p>p>p>p {color:blue;}
p>p>p>p>p>p {color:blue;}
p>p>p>p>p>p>p {color:blue;}
p>p>P>p>p>p>p>p {color:blue;}
</style>
</head>
<body>
<h1>A heading</h1>
<p>A paragraph.</p>
<p>Hello <span>web performance</span> students!</p>
<div><img src="awesome-photo.jpg"></div>
</body>
<script src="test.js"></script>
</html>
When you have inline script then it will execute faster than recalculate style even it doesn't manipulate your DOM or CSSOM and then recalculate style will execute one more time after HTML Parsing is completed in both Chrome and IE11.
<html>
<head>
<style>
h1 {color:red;}
p>p {color:blue;}
p>p>p {color:blue;}
p>p>p>p {color:blue;}
p>p>p>p>p {color:blue;}
p>p>p>p>p>p {color:blue;}
p>p>p>p>p>p>p {color:blue;}
p>p>P>p>p>p>p>p {color:blue;}
</style>
</head>
<body>
<h1>A heading</h1>
<p>A paragraph.</p>
<p>Hello <span>web performance</span> students!</p>
<div><img src="awesome-photo.jpg"></div>
<script>
var cnt=0
while(cnt++ <=9999999){}
</script>
</body>
<!-- <script src="test.js"></script> -->
</html>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With