Critical Rendering Path: The Foundation of Web Performance [Part 1]

pagarevijayy2 pts0 comments

Critical Rendering Path: The Foundation of Web Performance [Part 1]

Vijay's Newsletter

SubscribeSign in

Critical Rendering Path: The Foundation of Web Performance [Part 1]<br>A practical guide to browser rendering, performance bottlenecks, and production optimisations.

Vijay Pagare<br>Jul 30, 2026

Share

Most frontend performance problems arise due to lack of understanding of how the browser renders a page. When you deeply understand this process, you stop guessing what’s going wrong? You know why a page is slow, which part of the rendering pipeline is expensive, and which optimisation will actually make a difference.<br>I've spent a fair amount of time debugging slow pages, improving Core Web Vitals, and chasing Lighthouse regressions. Almost every issue eventually led back to one thing: the browser's rendering pipeline.<br>This article is a deep dive into that pipeline and the techniques I've found useful while optimising production applications.

What is the Critical Rendering Path?

The Critical Rendering Path (CRP) is the sequence of steps the browser follows to convert HTML, CSS, and JavaScript into pixels on your screen.<br>The browser roughly performs the following steps:<br>Parse HTML → Build the DOM

Parse CSS → Build the CSSOM

Combine both → Build the Render Tree

Calculate Layout

Paint pixels

Composite layers and display the frame

Every optimisation you make ultimately reduces the cost of one of these stages.<br>Let's understand each step.<br>1. Parsing HTML → Building the DOM

Everything starts with the HTML document.<br>As the browser receives the HTML response, it immediately starts parsing it from top to bottom. It doesn’t wait for the entire document to be downloaded first.<br>Each HTML element is converted into a tree-like structure called the Document Object Model (DOM) . The DOM represents the structure of your page.<br>While parsing the HTML, the browser also encounters other resources such as CSS and JavaScript. These influence the rendering pipeline differently, and understanding that difference is where most performance optimisations begin.<br>2. Parsing CSS → Building the CSSOM

Whenever the browser encounters a stylesheet, it starts downloading and parsing it into another tree-like structure called the CSS Object Model (CSSOM). This is a synchronous process.<br>CSSOM is necessary, because it tells the browser about the final appearance of an element. For example, a simple could have styles defined by: the browser’s default stylesheet, your global CSS, a component stylesheet, a utility class, a media query, pseudo selectors like :hover<br>Until all applicable rules are resolved, the browser cannot accurately render that element. This is why CSS is render blocking. It is by Design.<br>Common bottlenecks<br>Large monolithic CSS bundles

Unused CSS shipped to every page

Multiple blocking stylesheets

Slow network requests

Common optimisations<br>Remove unused CSS during the build.

Minify and compress CSS (Brotli/Gzip).

Cache static assets using a CDN.

Inline only the critical above-the-fold CSS.

Load non-critical CSS asynchronously.

Split CSS by route, template, or component where appropriate.

The goal is always the same: reduce the amount of CSS the browser needs before it can render the first screen.<br>3. JavaScript and the HTML Parser

Unlike CSS, JavaScript doesn’t block rendering. By default, it blocks HTML parsing .<br>When the browser encounters a synchronous tag, it pauses parsing the document, downloads the script, executes it, and only then continues parsing the remaining HTML.<br>Why? Because JavaScript can modify both the DOM and the CSSOM.<br>If the browser continued parsing while JavaScript was simultaneously changing the page, it could end up working with stale information.<br>Common bottlenecks<br>Large JavaScript bundles

Expensive script execution

Third-party scripts (like analytics)

Long-running tasks on the main thread

Common optimisations<br>Move non-critical scripts to the end of the document.

Use defer for application scripts.

Use async for independent scripts.

Lazy load code using route or component-based code splitting.

Break long tasks into smaller chunks.

Use Web Workers for CPU-intensive work.

Remove unnecessary polyfills.

Ship less JavaScript.

The fastest JavaScript is the JavaScript that never needs to be downloaded or executed. 😄<br>4. Building the Render Tree

By this point, the browser has built both the DOM and the CSSOM .<br>The next step is to combine them into a Render Tree .<br>The Render Tree contains only the elements that need to be rendered on the screen. Every node in the Render Tree contains both the structure (from the DOM) and the computed styles (from the CSSOM).<br>Not every DOM node becomes part of the Render Tree.<br>For example, elements with display: none are excluded because they don't participate in rendering. On the other hand, elements with visibility: hidden are included—they still occupy layout space even though they aren't visible.<br>Think of the Render Tree as the browser's...

browser rendering html javascript render tree

Related Articles