Browser Render Made Easy
Explaining the complex magic behind every web page
Elad Laor
August 19th, 2024
Lately I decided to revive an old hobby of mine: web development. In the past, I created lightweight web applications and visual simulator interfaces, but life took me in different directions, and I had to focus on my job.
A friend recommended I visit roadmap.sh to gain more knowledge and experience. One of the first articles in the frontend skill tree is about how the browser renders a web page, and it immediately fascinated me how complex this hidden process is.
We often take for granted the transition from clicking a link to seeing a fully loaded webpage, ignoring the intricate mechanics behind the scenes (well, did you think about it after clicking the link that led you here?).
Render who?!
"Rendering engines (also known as layout engines or browser engines) are part of a web browser that transforms HTML, CSS, and other resources of a web page into a visual representation on a screen." mdn web docs
The browser rendering engine is the one in charge of turning HTML and CSS to visual web pages like we know and love in a split of a second. There are several browser rendering engines (Blink for Chrome and Edge, WebKit for Safari, Gecko for Firefox, etc.). Lucky for us, all of them work similarly.
Our goal
In this article, I will explain and demonstrate the basics of browser rendering for fellow enthusiasts like myself. The goal is to make this topic as easy and understandable as possible while offering useful advice to improve our web development abilities. I will link to every resource I used, allowing you to explore further into this fascinating subject (it's a never-ending rabbit hole, trust me).
you must be familiar with at least basic knowledge of HTML and CSS in order to understand this article đ
Step 0 / Getting the resources
At the beginning there is only a blank web page. Hover / touch it and you will reveal our fully rendered web page (spoiler!).
The first step is the browser asking for the web page resources over the internet connection. There has to be a HTML file, most likely with a CSS file which contains the styling of the page. Of course there could also be Javascript, images and every file the web page needs.
Now that we have all of the resources, we will now follow each step the browser goes through in order to render its content.
Step 1a / Processing HTML
With the provided HTML file, the browser is using the Document Object Module (DOM) API to parse it, or simply, analyze and translate it into a format that can be understandable and manipulated - the DOM tree.
In JavaScript, when we are using document.querySelector(âpâ).innerHTML = âhello worldâ
we are actually not changing the HTML source code, but a property of the paragraph element in the DOM tree created by the browser. We couldn't do that without the DOM tree and its API.
This is our HTML code and the compatible DOM tree. You can edit the code to see the new DOM tree and also change the finished web page we will render accordingly.
Step 1b / Processing CSS
> Note: This step begins after the browser reads the <link>
tag (when parsing the HTML) and fetches the CSS file from the server. It can happen simultaneously with step 1a.
This process is similar to the one in step 1a. Without diving into technical details, the browser also parses any provided CSS stylesheet files.This time, the browser uses the CSSOM API, which is an interface that helps the browser understand and manipulate the styling of a page.
The CSS rules object is initially created, and each rule has a selector and its declarations in it:
Using the newly created rules object, the browser creates the CSSOM tree - a set of rules for the style and the layout of the page and all of its elements. Some of the style rules are inherited from the parent element (for example, when declaringfont-size: 10px
for the <body>
element, all of the paragraph elements <p>
inside it will also get this declaration).
Things we can do now that we know the CSSOM tree
It is less common to be familiar with the CSSOM compared to the DOM, but it could be sometimes useful. For example, when we declare document.querySelector("p").style.color = "red"
we may be thinking that we manipulate the CSS stylesheet file but it only adds inline style property like if we declared <p style=âcolor: redâ>example</p>
Using the CSSOM API we could actually manipulate the rules specified in our stylesheet file. In this case, document.styleSheets is the way to access all the stylesheets of our web page and manipulate them.
Did you ever want to create a different stylesheet for dark mode instead of changing classes for all the elements in your page? disable the light mode stylesheet by coding document.styleSheets[0].disable = true
and enable the dark mode stylesheet by codingdocument.styleSheets[1].disable = false
.
Using the CSSOM you could add, remove and edit specific style rules at your will! Explore more at Louis Lazaris's great article on this subject.
Note on performance
Creating the CSSOM tree can be time and resources consuming for the browser. The heavier the styles, the longer it takes to create the CSSOM tree and display the web page for the user. One solution is to use as few style rules as we can. Another solution is using atomic CSS. Google it, you will not regret this.
> Note: CSSOM is soon to be partially replaced by CSS Typed OM, which provides a more efficient and powerful way to interact with styles. However, itâs currently only supported by chrome and only specific features are available.
Step 2 / JavaScript
Next, the browser executes the JavaScript code. Actually, code execution starts whenever the HTML parser gets to the <script>
tag, unless the defer attribute is specified and then the execution starts after the HTML parsing is finished. Another option is the async attribute which then executes at the same time as the document parsing.
Some of the code could manipulate the DOM tree or the CSSOM tree.
Performance note
In order to improve performance, always use defer
or async
attributes if possible. If not, the user will have to wait until the JavaScript execution ends for the content to render. Read on performance in this great article by Fidal Mathew.
Step 3
The render Tree
> note: The browser will not get to this step until the DOM and CSSOM trees are created fully.
The browser merges the DOM and CSSOM trees to create the render tree, which represents all visible elements and their calculated styles.
The render tree is built by:
- Using the DOM tree to select only the visible elements - for example, the
<head>
element will not be rendered by default (unless itsdisplay: none
property is changed, apparently you can do that...). - Using the CSSOM tree to attach each element with its calculated styles.
The renderer follows fixed guidelines to build the render tree. For example, if more than 20 of the same element are nested within one another, it doesnât render the 20th and subsequent elements. Read more on the render in this amazing article by Paul Irish and Tali Garsiel.
This representation of the render tree is only partial - for example, it doesn't represent css rules that are not the type of CssStyleRule (like cssMediaRule, cssKeyframeRule...).
Note on performance: If hiding an element is needed - use display: none
instead of opacity: 0
if possible. This way the browser will not render something the user canât see anyway.
Step 4 / Layout (also called âreflowâ)
Using the newly created render tree, the browser calculates the size and position of every visible element on the page. The process applies the CSS rules from the render tree and the browserâs default styles to calculate the exact placement and dimensions of each element.
Step 5 / Painting
The browser fills in the pixels based on the layout and the styles from the render tree.
Now what?
Understanding how the browser works is not trivial. A lot of good and experienced front-end developers are still not familiar with it. Although it's a highly theoretical subject, there are some practical use cases for this knowledge. If you have feedback or further insights, feel free to reach out.
If you got interested, you can explore the following resources I used:
- Â How Browsers Work | Paul Irish and Tali Garsiel
- Async vs Defer in JavaScript: Which is Better? | Fidal Mathew
- An Introduction and Guide to the CSS Object Model (CSSOM) | Louis Lazaris
⸠Elad Laor, 2024