Critical Rendering Path: Understanding Browser Rendering

Mediumβ€’

Critical Rendering Path

Interview-safe ordering plus deeper browser pipeline details.

Rendering

Simplified CRP (Interview-safe)

HTML parse→
DOM→
CSSOM build→
Render tree→
Layout→
Paint→
Compositing

More complete browser pipeline

HTML download→
HTML parse→
DOM tree→
CSS download + parse→
CSSOM→
Style recalculation→
Render tree→
Layout→
Paint→
Rasterization→
Compositing

Preload scanner

Parallel discovery for CSS/JS/fonts/images while parser keeps running.

JavaScript blocking

Synchronous scripts can pause HTML parsing and mutate DOM/CSSOM before render.

Style recalculation

Rule matching + cascade/inheritance before geometry and paint.

Rasterization

Paint output is rasterized into tiles/layers before final compositing.

The critical rendering path is the browser pipeline that turns HTML, CSS, and JavaScript into pixels on the screen. For interviews, the simplified sequence DOM + CSSOM β†’ Render Tree β†’ Layout β†’ Paint β†’ Composite is correct. Senior-level nuance adds preload scanning, JavaScript parser blocking, explicit style calculation, and rasterization before final GPU compositing.

The Correct Answer

Best Answer for Interviews

HTML parsing β†’ DOM β†’ CSSOM β†’ Render Tree β†’ Layout β†’ Paint β†’ Composite

This is the best high-level answer among the choices.

Why This Is Correct but Simplified

That sequence is interview-safe and directionally correct. The fuller browser pipeline has extra stages and parallel work:

β€’HTML parsing starts as bytes arrive and builds DOM incrementally
β€’a preload scanner discovers CSS/JS/fonts/images in parallel
β€’synchronous JS can pause parsing and mutate DOM/CSSOM
β€’style calculation happens before layout
β€’modern pipelines include rasterization before final GPU compositing

A more complete sequence is:

HTML download β†’ HTML parse β†’ DOM β†’ CSS download/parse β†’ CSSOM β†’ Render Tree β†’ Style Calculation β†’ Layout β†’ Paint β†’ Rasterization β†’ GPU Compositing

Step 1: HTML Parsing and DOM Construction

HTML Parsing β†’ DOM

When the browser receives HTML:

1. Bytes are decoded into characters

2. Characters are tokenized

3. Tokens are parsed into nodes

4. Nodes are attached to the DOM tree

<html>
  <body>
    <h1>Hello</h1>
    <p>World</p>
  </body>
</html>

This produces a DOM structure representing the document.

Key Point

HTML parsing is incremental. The browser does not wait for the full document before starting to parse.

JavaScript Interaction

A normal script like this can pause parsing:

<script src="app.js"></script>

The parser stops, the script is fetched/executed, and only then does HTML parsing continue.

That is why defer is so important for non-critical scripts.

Step 2: CSS Parsing and CSSOM Construction

CSS Parsing β†’ CSSOM

When the browser discovers CSS:

<link rel="stylesheet" href="styles.css">

it fetches and parses the stylesheet into the CSSOM (CSS Object Model).

body { font-size: 16px; }
h1 { color: tomato; }
p { margin-top: 8px; }

The CSSOM contains style rules after resolving:

β€’selectors
β€’specificity
β€’cascade
β€’inheritance
β€’computed style inputs

Why CSS Matters for Rendering

The browser generally needs CSS before first render because it must know how visible DOM nodes should be styled.

Examples:

β€’display: none removes an element from layout and render tree
β€’font sizes affect layout dimensions
β€’positioning affects geometry

So although HTML parsing may continue while CSS is loading, CSS is effectively render-blocking for first paint by default.

Step 3: Render Tree Creation

DOM + CSSOM β†’ Render Tree

The browser combines DOM structure with computed style information to build the Render Tree.

The render tree includes only nodes relevant to visual rendering.

Included

β€’visible elements
β€’text nodes
β€’pseudo-elements that generate boxes

Excluded

β€’non-visual metadata like <head>
β€’<script> elements
β€’nodes with display: none

Important Distinction

visibility: hidden is different from display: none:

β€’display: none β†’ not in layout, not in render tree output for painting
β€’visibility: hidden β†’ still participates in layout, but is not visibly painted

Why Render Tree Comes Before Layout

The browser must know what boxes exist before it can calculate where they go and how big they are.

Step 4: Layout

Layout (Reflow)

Once the render tree exists, the browser performs layout.

Layout computes geometry for render tree nodes:

β€’width
β€’height
β€’x/y position
β€’line breaks
β€’box relationships

This is where the browser figures out the exact placement of content on the page.

Why Layout Can Be Expensive

Layout work can grow with DOM size and complexity. It may be triggered by:

β€’DOM insertions/removals
β€’style changes that affect geometry
β€’font changes
β€’viewport resize
β€’reading layout-dependent properties after writes
// Can force layout work in the wrong pattern
el.style.width = '200px';
const h = el.offsetHeight;

This kind of read-after-write pattern is a common performance problem.

Step 5: Paint

Paint

After layout, the browser paints visual parts of each box:

β€’text
β€’backgrounds
β€’borders
β€’shadows
β€’images
β€’decorations

Paint is about turning layout results into drawing instructions or pixels.

Important Distinction

Layout answers:

β€’where things go
β€’how big they are

Paint answers:

β€’what they look like

A change like color may trigger paint without requiring full layout.

A change like width often requires layout first, then paint.

Step 6: Composite

Composite

Modern browsers often split content into layers. During compositing, those layers are combined into the final frame shown on screen.

Properties that often help isolate work to compositing include:

β€’transform
β€’opacity

These are often cheaper to animate because they can avoid layout and sometimes avoid repainting large areas.

But Be Careful

Creating too many layers also has memory and management costs. Compositing is powerful, not free.

How the Given HTML Flows

Applying the Pipeline to the Example

Given:

<!DOCTYPE html>
<html>
<head>
  <link rel="stylesheet" href="styles.css">
</head>
<body>
  <h1>Hello World</h1>
  <p>Content here</p>
  <script src="app.js"></script>
</body>
</html>

A realistic timeline looks like this:

1. Browser starts HTML parsing

2. Preload scanner starts parallel resource discovery

3. <link rel="stylesheet"> is discovered and CSS fetch starts

4. DOM continues building incrementally

5. Browser reaches <script src="app.js">

6. Parsing pauses while script fetch/execute runs (unless defer/async)

7. CSSOM + DOM become available for renderable nodes

8. Render tree is built

9. Style calculation finalizes computed styles

10. Layout runs

11. Paint runs

12. Rasterization prepares tiles/layers

13. GPU compositing produces final frame

Interview Takeaway

The best mental model is not β€œeverything finishes, then next step starts forever.”

It is:

β€’parsing is incremental
β€’resource discovery happens during parsing
β€’scripts can interrupt parsing
β€’style and geometry are distinct phases
β€’simplified pipeline is fine for interviews, but full browser internals include rasterization and GPU compositing

Common Misconceptions

Misconception 1: CSSOM always finishes before DOM

Not necessarily.

DOM construction often starts first because HTML parsing starts immediately. CSSOM starts when CSS is discovered. They may overlap in time.

Misconception 2: Layout happens before Render Tree

Wrong.

The browser must know which renderable boxes exist before it can compute their geometry.

Misconception 3: Paint and Composite are the same

They are related but different:

β€’Paint draws visual contents for boxes/layers
β€’Composite assembles layers into the final frame

Misconception 4: CSS blocks HTML parsing

Usually not directly.

CSS blocks rendering, not raw HTML tokenization itself. However, interaction with scripts can make the overall pipeline feel blocked because scripts may need up-to-date style information.

Misconception 5: The DOM is the same as what gets painted

Also wrong.

The render tree is derived from DOM + style information and excludes non-rendered nodes.

Performance Implications

How to Speed Up the Critical Rendering Path

1. Reduce render-blocking CSS

β€’inline truly critical CSS
β€’split non-critical CSS
β€’remove unused CSS

2. Avoid parser-blocking JavaScript

Use defer for scripts that do not need to run immediately:

<script defer src="app.js"></script>

defer lets HTML parsing continue and runs the script after parsing, before DOMContentLoaded.

3. Reduce layout work

β€’batch DOM reads and writes
β€’avoid layout thrashing
β€’prefer changing classes over many inline style mutations

4. Prefer compositor-friendly animations

Animate transform and opacity when possible.

Real Interview Framing

When interviewers ask about rendering performance, they often want you to connect optimizations to pipeline stages:

β€’smaller CSS β†’ faster CSSOM / less render blocking
β€’deferred JS β†’ less parser blocking
β€’fewer geometry changes β†’ less layout work
β€’smarter animations β†’ cheaper paint/composite behavior

Follow-up Interview Questions

Q: Why is this sequence correct if DOM and CSSOM can happen in parallel?

Because this is the best conceptual ordering among the choices. DOM construction begins first, CSSOM is built when CSS is discovered, and the render tree depends on both.

Q: What does a normal `<script>` do during parsing?

It pauses HTML parsing at that point, fetches and executes the script, then resumes parsing.

Q: What changes trigger layout?

Examples include:

β€’width/height changes
β€’margin/padding changes
β€’DOM additions/removals
β€’viewport resize
β€’font metric changes

Q: What is the difference between `display: none` and `visibility: hidden`?

β€’display: none removes the element from layout flow
β€’visibility: hidden keeps layout space but hides the visual output

Q: How do you improve First Contentful Paint?

β€’reduce render-blocking CSS
β€’defer non-critical JS
β€’optimize server response and HTML delivery
β€’preload truly critical resources
β€’minimize expensive layout and paint work