Browser rendering pipeline

Dive into parsing html, css and js to render the page

November 18, 2024

Review the browser workflow

In the browser workflow from downloading resources to rendering the page part 1, we have reviewed what's behind the browser workflow when user enters a URL and press enter, then in article browser workflow from downloading resources to rendering the page part 2, we have reviewed the detailed process of how the browser handles the request and response.

Now, it's time to dive into the browser rendering pipeline.

HTML parsing

After the TCP connection is established, and the HTTP/HTTPS response is received, the browser will request the HTML resources from server, then start to parse the HTML, and convert the HTML into a DOM tree.

When encountering external CSS or internal CSS or inline style, does browser parse them immediately? Or wait for the HTML parsing to complete? Or both?

CSS parsing

External CSS (link tag)

When CSS loaded via link tag (<link rel="stylesheet" href="style.css">), this is render-blocking by default, but doesn't block HTML parsing and DOM construction.

Internal CSS (style tag)

When CSS within style tag (<style>...</style>), this won't block HTML parsing and DOM construction, since it's already part of the HTML, hence no additional downloads.

Inline CSS (style attribute)

When CSS within style attribute (<div style="color: red;">), this won't block HTML parsing and DOM construction, since it's already part of the DOM.

So we can say that whether CSS is loaded via link tag, style tag or inline style, it doesn't block HTML parsing and DOM construction, they are parallel processes (means they are not blocking each other).

Just like HTML, browser will parse these CSS resources and convert them into a CSSOM tree (CSS Object Model).

HTML Download -> DOM Construction
               -> External CSS Download -> CSS Parsing -> CSSOM Construction -> Render Tree -> Rendering
               -> Internal CSS Parsing -^
               -> Inline CSS Parsing --^

JavaScript parsing

JavaScript is much complex than HTML and CSS, because JS can manipulate the DOM and CSSOM, there are three ways to load JS:

Regular script tag (without defer or async)

<script src="script.js"></script>

When JS loaded via script tag, this will block HTML parsing, and it needs to wait for previous CSS download and parsing and complete CSSOM construction.

Defer script tag

<script src="script.js" defer></script>

Will wait for HTML parsing and DOM construction, CSS download, parsing and CSSOM construction.

Note: Script with type="module" automatically uses defer by default.

Async script tag

<script src="script.js" async></script>

Will not block HTML parsing, when JS is downloaded, it will execute immediately without waiting for previous CSS download, parsing and CSSOM construction, so it can be executed without DOM is ready.

When to use defer vs async?

defer use cases

  1. It the script that manipulate the DOM.
  2. Multiple scripts that need to be executed in a specific order.
  3. Speed up the initial page load.

async use cases

  1. Independent functionality scripts.
  2. Tracking and analytics scripts.
  3. Ads scripts.

Summary

  1. Browser will request HTML resource first, then parse HTML and construct DOM tree.
  2. When encountering external CSS or internal CSS or inline style, browser will parse them and construct CSSOM tree, it will block rendering, but this won't block HTML parsing and DOM construction.
  3. When encountering JS, it depends on the attribute of script tag:
    • if it's regular script tag, it will block HTML parsing and DOM construction.
    • if it's defer script tag, it will wait for HTML parsing and DOM construction, it will execute in order.
    • if it's async script tag, it execute immediately after download, it will not block HTML parsing and DOM construction, may encounter error accessing DOM and CSSOM.
Back to Blog 🏃🏽‍♀️