Conceptly
← All Concepts
🎨

Critical Rendering Path

performanceThe browser's rendering pipeline that turns HTML into screen pixels

The Critical Rendering Path (CRP) is the sequence of steps the browser takes from receiving an HTML file to painting the first pixels on screen. It encompasses parsing HTML into a DOM tree, building a CSSOM from stylesheets, merging them into a Render Tree, calculating layout, painting pixels, and compositing layers. Understanding this pipeline reveals where time is lost between receiving a response and seeing content, and which resources block that process.

β–ΆArchitecture Diagram

πŸ”„ Process

Dashed line animations indicate the flow direction of data or requests

Why do you need it?

It is not intuitively obvious why the time from receiving an HTML file to the first pixel appearing on screen can be long. A single CSS file can block rendering of all HTML below it simply because of its position, or a single `<script>` in the `<head>` can halt parsing entirely -- facts that are not visible just from looking at the source. Without knowing where time is being lost, even looking at performance measurements does not tell you what to fix.

Why did this approach emerge?

Early web browsers read HTML top to bottom and drew the screen as they went. When styles and scripts were inline or absent, this linear processing was simple and intuitive. As external CSS files and JavaScript became standardized, browsers faced the problem of flickering when rendering before styles were finalized, and chose to wait for CSSOM completion before building the Render Tree. The rule of pausing the parser when encountering a script -- because JavaScript could dynamically modify the DOM -- also emerged. These accumulated decisions shaped the current Critical Rendering Path.

How does it work inside?

When the browser receives HTML bytes, it converts them into tokens and builds a DOM tree. Simultaneously, encountering a `<link rel="stylesheet">` triggers fetching the CSS file and building a separate CSSOM tree. CSS is a render-blocking resource. Without a completed CSSOM, the Render Tree cannot be built, so the later the CSS file arrives or the larger it is, the more delayed the first screen becomes. A `<script>` tag is also a parser-blocking resource. Because the browser assumes the script could modify the DOM, it pauses HTML parsing and waits for the script to execute unless the `defer` or `async` attribute is present. Once DOM and CSSOM are ready, they are merged into a Render Tree. Elements with `display: none` are excluded from the Render Tree. In the Layout (or Reflow) stage, the size and position of each node is calculated. In the Paint stage, colors and borders are filled into pixels. Finally, in the Composite stage, the GPU merges layers and outputs the result to the screen. When JavaScript alternates between reading and writing DOM layout properties, Layout is re-executed multiple times -- this is Layout Thrashing. Batching reads first and writes second reduces this waste.

Boundaries & Distinctions

CRP and DOM are closely linked but cover different scopes. The DOM is the in-memory structure representing the HTML document; CRP is the entire pipeline from DOM creation through screen output. Understanding the DOM lets you follow cause and effect in CRP -- which operations trigger Layout or Paint and why. The distinction from SSR (Server-Side Rendering) also becomes clear here. SSR sends pre-built HTML from the server, so the browser's initial DOM construction is faster than in an SPA that starts with empty HTML. But CSS and JavaScript render-blocking occurs identically in SSR. CRP optimization applies regardless of rendering approach. CSS properties like `transform` and `opacity` trigger only the Composite stage, so they skip Layout and Paint and are advantageous for animations. Properties like `width`, `height`, `margin`, and `top`, on the other hand, force Layout recalculation and carry significant performance cost.

When should you use it?

CRP understanding becomes practically necessary when Lighthouse flags Render-Blocking Resources, or when FCP or LCP are higher than targets. To find the cause, you need to identify which CSS and JS files must complete before the first screen can render. `<link rel="stylesheet">` is render-blocking by default, so separating styles not needed for the first screen into a separate file and using the `media` attribute or dynamic insertion for non-blocking treatment is worth considering. Adding `defer` or `async` to `<script>` tags alone can avoid HTML parsing blockage. When JavaScript mixes reading and changing layout-related properties, the browser is forced to execute Reflow in between. If the Performance tab in DevTools shows Layout appearing abnormally often, this pattern should be suspected. Not every stage needs optimization. If first-screen entry metrics are within target ranges, animations that trigger only Composite and deferred JS are usually sufficient to meet most requirements.

First-screen optimization -- identifying render-blocking resources to improve FCP and LCP metricsCSS/JS loading strategy -- analyzing how stylesheet and script placement affects renderingLayout thrashing debugging -- identifying patterns where JavaScript repeatedly reads and writes to the DOM, triggering repeated ReflowsAnimation performance -- choosing CSS properties that trigger only Composite, avoiding Layout and Paint