How the browser draws pages

How HTML, CSS and JS code is processed before it becomes a web page.

To draw the result of our code on the screen, the browser needs to perform several steps:

First he needs to download the sources.

Then they need to be read and parsed.

After that, the browser starts rendering – rendering.

Each of the processes is very complex, and we will not consider them to the smallest detail.

We will only pay attention to the details that frontend developers need to know in order to better understand why different solutions have different effects on performance and rendering speed.

Let’s start in order.

Getting Resources, Fetching

The section of the article “Getting resources, Fetching”

Resources the browser receives using requests to the server. In response, it can receive, for example, data in the form of JSON, as well as images, videos, style files and scripts.

The very first request to the server is usually a request to get an HTML page (most often index.html ).

Its code contains links to other resources that the browser will also request from the server:

<!DOCTYPE html>

<html lang=”en”>

  <head>

    <link href=”/style.css” rel=”stylesheet”>

    <title>Document</title>

  </head>

  <body>

<script src=”/index.js”></script>

  </body>

</html>

In the example above, the browser will also request:

  • style.css style file;
  • image hello.jpg;
  • and the index script.js.

Parsing, Parsing

As the HTML page is downloaded, the browser tries to “read” it – parse it.

DOM

The browser does not work with markup text, but with abstractions above it. One of these abstractions, the result of HTML code parsing, is called DOM.

DOM (Document Object Model) is an abstract representation of an HTML document with which the browser can access its elements, change its structure and design.

DOM is a tree. The root of this tree is an HTML element, all other elements are child nodes.

For such a document:

<html>

  <head>

    <meta charset=”utf-8″>

    <title>Hello</title>

  </head>

  <body>

    <p class=”text”>Hello world</p>

    <img src=”/hello.jpg” alt=”Hello!”>

</body>

</html>

it …you will get such a tree:

                  html

        ____________|________

        |                    |

      head                  body

    ____|____              ___|___

    |       |             |       |

    meta   title          p      img

            |             |

          ‘Hello’    ‘Hello world’

While the browser is parsing the document and building the DOM, it comes across elements like <img>, <link>, <script> that contain links to other resources.

If the resource is non-blocking (for example, an image), the browser requests it in parallel with parsing the rest of the document. Blocking resources (for example, scripts) suspend processing until they are fully loaded.

We can tell the browser exactly how it should request some resources, for example, scripts. This can be useful when in a script we are going to work with elements that are in the markup after the <script> tag:

// script.js

const image = document.getElementById(‘image’)

<body>

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

</body>

In this case, image === undefined, because the browser managed to parse only part of the document before this <script> tag.

And in this everything is in order, the image will be found:

<body>

</body>

Copy

And this is also the order, the defer attribute will tell the browser to continue parsing the page and execute the script later:

<body>

</body>

Copy

CSSOM

Section of the article “CSSOM”

When the browser finds a <link> element that points to a style file, the browser downloads and parses it. The result of CSS code parsing is CSSOM.

CSSOM (CSS Object Model) — by analogy with DOM, a representation of style rules in the form of a tree.

For the document above with such styles:

body {

  font-size: 1.5rem;

}

.text {

  color: red;

}

img {

  max-width: 100%;

}

Copy

it …we get such a tree:

            body

      (font-size: 1.5rem)

      ________|_________

      |                 |

    .text              img

(color: red)    (max-width: 100%)

Reading styles pauses reading the page code. Therefore, it is recommended at the very beginning to give only critical styles — which are on all pages and specifically on this one. This way we reduce the waiting time until the “page loads”.

📝

Thanks to optimizations (for example, a preload scanner), styles may not block HTML reading, but they definitely block JavaScript execution, because CSS selectors can be used in JS to select elements.

Render Tree

Section of the article “Render Tree”

After the browser has compiled the DOM and CSSOM, it combines them into a common rendering tree — the Render Tree.

Render Tree is a term that is used by the WebKit engine, it may differ in other engines. For example, Gecko uses the term Frame Tree.

As a result, for our document above, we will get such a tree:

              html

                |

              body

        (font-size: 1.5rem)

        ________|________

        |               |

      p.text           img

    (color: red)  (max-width: 100%)

        |

  ‘Hello world’

Note that only visible elements get into the Render tree. If we had an element hidden via display: none, it would not have got into this tree. We will talk about this in more detail later.

Leave a Reply

Your email address will not be published. Required fields are marked *