Critical Rendering Path

<< Hello World! It is great to have you here !!

Have you ever wondered what goes on behind the scenes when you load a web page? How does the browser transform the raw HTML, CSS, and JavaScript code into a visually appealing and interactive website? If you've ever pondered these questions, then you've stumbled upon the fascinating realm of the Critical Rendering Path (CRP).

The Critical Rendering Path (CRP) is the sequence of steps that the browser takes to render a webpage on the user's device.

The steps include creating the DOM, and CSSOM, generating the Render Tree, performing the layout, and finally painting the screen with pixels.

1. Document Object Model ( DOM ) Creation

The construction of DOM is an incremental process. But what does it mean?

Data is received in chunks over the network. When we get chunks of HTML file ( partial HTML of the entire file ), we can start constructing the DOM.

HTML5 specification specifies a certain set of rules for how we should process the received data.

The stream of characters from HTML file is parsed into tokens by the tokenizer. While the tokenizer is producing tokens, there is another process that is consuming these tokens to produce DOM Nodes. Finally, all these Nodes are arranged to form a DOM tree which captures the content and properties of the HTML and all the relationships between the nodes.

2. Creation of CSS Object Model ( CSSOM )

When we get the reference of a CSS file while parsing the HTML an HTTP request is sent to fetch the CSS file ( meanwhile further parsing of HTML continues ). Now if the DOM generation is complete, nothing is displayed on the screen ( a blank screen ) yet because we haven't received the CSS yet. We are blocked, until we have the style information we cannot put anything on the screen.

Unlike HTML parsing, CSS is not incremental because of the cascading rule set it has, the entire CSS file needs to be fetched before we can start the creation of CSSOM.

Rendering is blocked on CSS. So it is critical for loading fast applications and you have to get those as quickly as possible to the user.

To do that we can inline some critical style, or if we have a huge CSS file but if a page requires only some specific style, we can split it and load accordingly.

3. Generation of Render Tree

When DOM and CSSOM are generated, they are combined to form a Render Tree. The Render Tree only captures visible content. Any elements with display property set to none are not part of the Render Tree even though they are a part of DOM.

4. Layout Phase

<meta name="viewport" content="width=device-width" >

We have the above meta tag in the HTML file. It is telling the width of the layout viewport should be equal to the device width.

Suppose the device width is 300px and if we have a div of width 50%, then the size would be 150px. Such calculation happens are performed in the layout phase.

Based on the render tree, the browser calculates the position and size of every element which is called the Layout Phase. If the dimensions of the viewport change, the browser runs the layout phase again, that is what happens when we rotate our phone.

5. Paint Phase

Finally, the browser creates a visual representation of the render tree on the screen ( Paint Phase ).

Javascript

This is how it briefly works, but we forgot about the most important part of the web application i.e., JAVASCRIPT.

How does JS load inside the browser?

When the HTML parser encounters a script tag, it stops the parsing of the HTML, fetches the script and when the script is downloaded, it executes the script ( on the main thread ) and then only the HTML parsing resumes.

This is render blocking. Parser has to stop, fetch script & then execute, and then resume parsing.

With async attribute: When a script tag is encountered, script is fetched on a different thread and HTML parsing is not blocked but when the script gets downloaded, it will be executed blocking the parsing. No guarantee of order of execution.

With defer attribute: When a script tag is encountered, script is fetched on a different thread, and when the script gets downloaded, it will wait for HTML parsing to over before executing the script. It guarantees the order of execution.

Brief overview of a frame

Imagine your website is set to render at 50 frames per second, providing a fluid and responsive user interface. With each frame lasting approximately 20 milliseconds, you have a limited window to execute crucial tasks and ensure timely updates are displayed.

When an asynchronous event occurs, triggering a corresponding handler, the clock starts ticking. Within that 20-millisecond time slot, various tasks need to be completed to present the updated view on the viewport. Let's take a look at these vital steps:

  1. Application Code: Your code logic needs to swiftly process the event and perform the necessary computations or manipulations.

  2. Garbage Collection: Cleaning up unused memory and resources becomes imperative to maintain optimal performance and prevent any memory leaks.

  3. Layout Recalculation: The browser must determine the positions and dimensions of the elements on the page, factoring in any changes triggered by the event.

  4. Style Recalculation: Based on the updated layout, the browser reevaluates the styles and determines how each element should be visually presented.

  5. Painting: With styles determined, the browser applies the necessary colors, images, and visual effects to create the final appearance of the page.

The challenge lies in completing all these tasks within the 20-millisecond timeframe. If the execution time exceeds this limit, the next frame is dropped, leading to a less-than-optimal user experience. The browser adheres to a strict rendering schedule, with updates to the screen's painting occurring precisely at the 20-millisecond mark.

This is it for the blog. Hope this added value to your learning and you explored something new. Happy coding, and may your websites always load like lightning!

Thank You!!