← Back to list

How browser rendering works?

The entire browser rendering process happens in a few milliseconds, but it involves a lot of steps (Critical Rendering Path).

Rahul Sharma · 2025-02-25 12:49 · 0 claps · 6.7 min read
#browsers #document-object-model #cssom #render-tree #layout
Open on Medium ↗
Wiki topics: 🌐 · Web Development

How browser rendering works?

Photo by Panos Sakalakis on Unsplash

Photo by Panos Sakalakis on Unsplash

The entire browser rendering process happens in a few milliseconds, but it involves a lot of steps (Critical Rendering Path).

The Critical Rendering Path (CRP) refers to the sequence of steps a browser takes to convert HTML, CSS, and JS into pixels on the screen. Optimizing this path is crucial for improving page load performance and ensuring a smooth experience.

Steps Involved

Browser Rendering Steps Involved

Browser Rendering Steps Involved

DOM

When a browser receives an HTML document, it begins by parsing the file. Let’s take an example of the below HTML snippet.

<html>
  <head>
    <title>Page Title</title>
  </head>
  <body>
    <h1>Hello</h1>
    <p>This is a paragraph.</p>
  </body>
</html>

The first step would be to fetch the HTML. Once we have the html text with us, it is then tokenized.

What’s a tokenizer?

The tokenizer is a finite state machine that reads raw HTML text and converts it into tokens incrementally as the browser reads the HTML text stream.

These tokens include start tags (<div>), end tags (</div>), attributes (class=”wrapper”), text content, and special characters.

Below is what the tokenizer would do to the example in consideration:

Token: StartTag(html)
Token: StartTag(head)
Token: StartTag(title)
Token: Character("Page Title")
Token: EndTag(title)
Token: EndTag(head)
Token: StartTag(body)
Token: StartTag(h1)
Token: Character("Hello")
Token: EndTag(h1)
Token: StartTag(p)
Token: Character("This is a paragraph.")
Token: EndTag(p)
Token: EndTag(body)
Token: EndTag(html)

Next step is Tree Construction — This involves constructing a Parsed tree to begin with. This tree basically depicts the structure of the HTML document and its nodes.

Document
├── html
│   ├── head
│   │   └── title
│   └── body
│       ├── h1
│       └── p

This parsed tree when built, gets converted into a DOM tree (see below).

Document
├── HTMLHtmlElememnt (html)
│   ├── HTMLHeadElement (head)
│   │   └── HTMLTitleElement (title)
│   └── HTMLBodyElement (body)
│       ├── HTMLHeadingElement (h1)
│       └── HTMLParagraphElement (p)

A DOM is a tree structure representing the HTML document where each HTML element becomes a node in the tree and their attributes and text content become children.

*Note: Each node in the DOM is an object that browser can manipulate (via JavaScript*).

Reentrancy in HTML Parsing

  • HTML parsing in the browser is reentrant, meaning it can be paused and resumed based on external events, such as JavaScript execution.
  • This is important because JavaScript can modify the DOM while parsing is in progress.

CSSOM

CSSOM stands for Cascading Style Sheet Object Model. It’s a set of APIs allowing the manipulation of CSS from JS.

CSSOM is a representation of the CSS styles applied to a web page. It works alongside the DOM but specifically handles CSS rules and their relationships.

For e.g., below CSS has the following CSSOM tree generation:

body {
  font-size: 16px;
}
p {
  color: blue;
}
CSSOM
├── body { font-size: 16px; }
└── p { color: blue; }

*Note: *Each node represents a CSS rule. These rules are cascading, meaning child elements inherit styles from parent nodes.

Also, modifying the CSSOM is expensive because it triggers reflows and repaints.

Render Tree

Once the DOM and CSSOM are built, the browser constructs the Render Tree. It’s made by combining both and only contains elements that are visible (e.g., elements with display: none, and non-visual elements like head, script, title, etc. are not included).

Most important thing to note is that each node in the render tree has calculated styles (a.k.a Render Styles) applied to it and is known as a Render Object. So in this step, a DOM node is basically converted into a Render Object. Also, each render object has a reference to the corresponding DOM node as well.

For e.g.,

Render Tree
├── html (visible)
│   ├── body (visible, font-size: 16px)
│   │   ├── h1 (visible, inherits font-size)
│   │   ├── p (visible, font-size: 16px, color: blue)

This generated Render Tree now serves as an input for the layout calculations.

Before diving into Layout, it’s important to understand Render Layers.

Render Layers

The Render Tree consists of individual Render Objects (which represents visual elements on the webpage). Some of these elements are grouped into Render Layers, which determine how they are painted on the screen.

When are Render Layers created?

Render Layers are formed in cases like:

  • Positioned Elements (position: fixed | absolute) — These elements are taken out of the normal document flow and get their own layer.
  • Elements with opacity < 1 or mix-blend-mode — When elements have transparency or blending, they need a separate layer for correct composting.
  • 3D Transforms (transform: translateZ(0), perspective) — Any element with 3D transformations creates a new layer.
  • Canvas, Video, and iFrames — Heavy media content is often placed in its own layer for better performance.
  • Will-change (will-change: transform, opacity) — This tells the browser to prepare a new layer ahead of time, optimizing animations.

Note that render layers are important because changes in one layer don’t affect others, thus unnecessary repaints can be reduced if something changes in a layer. But if too many elements create new layers, it can also slow down rendering.

Layout

A.k.a Reflow, Up until here we have got our render tree and all its visual information in different Render Objects, Now we just need to lay them out!

The browser calculates the position and size of each element on the page, basically “Where a node will be on the screen?”, based on the information stored in Render Objects.

It starts from the root-most element (html) and calculates the following for each node:

  • Width, Height
  • Margins, Padding, Border
  • Position (relative to parent elements)

Once the browser has above information for each node, it flows each elements into their appropriate locations based on their styles (e.g. position: absolute, float, grid, etc.).

Note: If a change affects the size of an element, reflow occurs, recalculating the layout. It’s the best practice to avoid having changes that trigger frequent reflows, aka. Layout Thrashing.

A little something about Dirty Bit System in Browser Rendering,

A Dirty Bit System is an optimization technique used in browser rendering to minimize unnecessary recalculations when updating the Render Tree. It helps the browser track which elements need to be re-laid out and which ones can be skipped, improving performance.

How the Dirty Bit System works?

**Tracking Changes

  • When an element’s layout-related properties changes (e.g. width, height, position, margin), the browser marks it as “dirty”** (flagged for re-layout).

Propagation to Parents - If an element is marked dirty, its parent may also need to be marked dirty if its size or position depends on the changed element. - For e.g., if a child div has a change in width, its parent might need a re-layout if it’s using display: grid or flex .

Minimizing Recalculations - The browser only recomputes the layout for dirty elements and their affected parents instead of recalculating the layout of entire page avoiding unnecessary layout thrashing, thus improving rendering efficiency.

Immediate Layout

An Immediate Layout or Forced Synchronous Layout happens when JS forces the browser to calculate layout synchronously before making further changes. This often occurs when you query layout-dependent properties right after modifying the DOM.

element.style.width = "100px"; // Modify Layout
console.log(element.offsetWidth); // Forces Immediate Layout

This is bad because it pauses JS execution, computes styles, and performs layout calculations immediately.

Global Layout

A Global Layout or Full Page Reflow occurs when a layout change affects multiple elements, requiring the browser to recompute the entire page’s layout.

document.body.style.fontSize = "20px"; // May trigger a global layout change

Here, the browser must recompute the positions of multiple elements, which is more expensive than a localized layout change.

Other things like adding or removing DOM elements dynamically, and resizing the browser window can also trigger a full page reflow.

A better way to avoid such reflows is basically using CSS classes more instead of inline styles or using requestAnimationFrame() to batch layout changes efficiently.

Painting

Aka., Rasterization. Post the layout calculations, the browser starts to paint the lay’ed out render tree on the screen. It creates layers based on position, z-index, etc. and paints from bottom up, painting each layer separately.

How does a single layer painting works through?

By converting each element in that layer into pixels. Their backgrounds, borders, text, images, and shadows are drawn.

If we discuss in depth, the browser traverses the render tree and calls paint() function on each node to determine how it should be drawn.

Composting

These Layers are then sent to the GPU for rasterization (turning vector instructions into actual pixels) — Basically, a bitmap is produces for each layer and that bitmap is uploaded to the GPU as a texture, the GPU then composites the textures into a final image to render to the screen.

BitMap Image

BitMap Image

Modern browsers split the page into layers to improve the performance.

For e.g., position: fixed or will-change: transform elements might be placed in a separate compositor layer. The GPU blends these layers together in a process called composting.

Why is it important?

Composting ensures smooth animations and helps with the hardware acceleration as it avoids redrawing the entire page when a small part changes in it.

This concludes this article here. I hope you got an overview of what happens in the browser rendering process. It follows from the article, “What happens when you type something in URL search bar?”, which dives into important concepts like URL, Hosts, DNS, SSL, etc. Feel free to check it out.

[embed]What happens when you type something in URL search bar? When you enter a website name in the URL bar of your browser, a series of intricate processes occur behind the scenes…medium.com


메타데이터
post_id
aeaa408bcb91
slug
how-browser-rendering-works-aeaa408bcb91
url
https://medium.com/@everythingwebber/how-browser-rendering-works-aeaa408bcb91
canonical_url
https://medium.com/@everythingwebber/how-browser-rendering-works-aeaa408bcb91
author_url
https://medium.com/@everythingwebber
status
ok
fetched_at
2026-06-26 06:47:43