How Browsers Render Web Pages: The Critical Rendering Path

Introduction

When you open a website, the browser does more than show a file. It parses markup, builds trees in memory, calculates geometry, paints pixels, and composites layers onto the screen. That sequence is the critical rendering path.

Frontend performance problems almost always map to one of these stages: slow first paint, layout shift, janky scrolling, or a main thread blocked by JavaScript. Chrome, Edge, Safari, and Firefox share the same conceptual pipeline even though their engines differ (Blink, WebKit, Gecko).

This guide explains how browsers turn HTML, CSS, and JavaScript into pixels, with architecture, data flow, and examples you will see in real apps.

Simple Explanation

Treat rendering like converting a recipe into a plated dish.

  • HTML is structure: headings, paragraphs, images.
  • CSS is presentation: size, color, position.
  • JavaScript can rewrite the recipe while the kitchen is already cooking.

The browser cannot paint a useful first frame until it knows both what exists and how it should look. That is why CSS blocks first paint. JavaScript can also pause HTML parsing because a script may insert or rewrite markup.

After structure and style are known, the engine still must decide which nodes are visible, compute pixel sizes and positions, draw those boxes, and stack layers into a frame.

How It Works Internally

A Chromium-style browser splits work across processes:

User navigates
    |
    v
Browser process (UI, network, navigation)
    |
    v
Network: DNS, TCP/TLS or QUIC, HTTP response
    |
    v
Renderer process
  - Main thread: parse, style, layout, JavaScript
  - Compositor thread
  - Raster threads
    |
    v
GPU / OS compositor -> pixels

The critical rendering path lives in the renderer process.

1. HTML becomes the DOM

The HTML parser tokenizes bytes and builds a tree of nodes. That tree is the Document Object Model (DOM). JavaScript can read and mutate it.

Parsing is incremental. A preload scanner watches tokens and starts fetching CSS, scripts, and images early.

A classic script tag with src pauses parsing because the script may call document.write. Use defer (run after parse, in order), async (run when ready), or ES modules (deferred by default).

2. CSS becomes the CSSOM

Stylesheets are parsed into the CSS Object Model (CSSOM). Later rules can override earlier ones, so the engine waits on relevant CSS before first paint. An external stylesheet in the head is render-blocking. A print stylesheet with media=print is not.

Style calculation then matches rules to DOM nodes and computes used values, including inheritance and specificity.

3. Render tree

The engine merges DOM and CSSOM into a render tree.

  • display:none nodes are omitted and take no space.
  • visibility:hidden nodes are included: they occupy space but are not drawn.
  • Non-visual elements such as head are omitted.

4. Layout (reflow)

Layout assigns each box an x, y, width, and height. Percentages, flex, and grid resolve into pixels. Changing a parent width can change every child, so layout is often expensive.

Layout thrashing happens when JavaScript interleaves geometry reads and style writes in a loop. The engine must flush layout so values such as offsetWidth are correct. Batch reads first, then writes.

5. Paint

Paint turns boxes into drawing commands and then pixels: fill a rectangle, draw text, blit an image. Changing color often needs paint only. Changing width needs layout and then paint.

6. Composite

Some content is promoted to layers (video, a transformed card, will-change: transform). The compositor stacks layers, often on the GPU and off the main thread.

Animating transform and opacity can skip layout and paint. Animating top or height cannot.

HTML -> DOM
CSS  -> CSSOM
         +-> Render tree -> Layout -> Paint -> Composite -> Screen
JavaScript may mutate the trees and restart later stages.

Real-World Examples

Marketing homepage. The preload scanner requests CSS and a hero image. A blocking script in the head delays parse. First paint waits on CSS. Largest Contentful Paint is often the hero image or heading. A late webfont can hide text or shift layout (CLS).

Single-page app. The first HTML may be a shell. JavaScript builds the real DOM. Until that bundle runs, the user sees little. Hydration attaches events to server HTML; a mismatch forces extra work.

Long lists. Inserting thousands of nodes makes style and layout expensive. Virtualization keeps only visible rows in the DOM.

Stuttering animation. Animating height reflows every frame. Animating transform on a composited layer can stay smooth even if JavaScript is busy.

Chrome DevTools Performance recordings name the same stages: Parse HTML, Evaluate Script, Recalculate Style, Layout, Paint, Composite Layers.

Code Examples

Put render-critical CSS in the head. Defer application JavaScript. Give images width and height so they reserve space and do not cause layout shift.

Avoid layout thrashing: read container.offsetWidth once, then write el.style.width in a loop. Do not read offsetWidth after each write.

Prefer CSS like transform and opacity for open/closed panels instead of animating height or top.

Common Misconceptions

The browser paints HTML top to bottom like a printer. Parsing is roughly sequential, but first paint waits on CSS, and stacking contexts control paint order.

display:none and visibility:hidden are the same. Only display:none leaves the render tree. Hidden elements still take space.

More compositor layers always help. Layers use memory. Promote only elements that actually animate or scroll independently.

All JavaScript blocks rendering. Classic head scripts do. Deferred modules do not block parse the same way. Long main-thread tasks still delay the next frame and input (INP).

HTTP/2 or HTTP/3 changes how pixels are drawn. They change delivery, not the DOM/layout pipeline. Faster CSS and font delivery still shortens the critical path.

Once painted, work is finished. Scroll, hover, animation, and DOM updates retrigger style, layout, paint, or composite. Rendering is a loop.

Best Practices / Key Takeaways

  • Shorten the path: fast HTML, small critical CSS, deferred application JavaScript.
  • Keep render-critical CSS in the head. Do not hide the only stylesheet behind a JS bundle.
  • Prefer defer or modules over synchronous scripts in the head.
  • Set image dimensions or aspect-ratio to reduce CLS.
  • Measure LCP, INP, and CLS. They map to paint, input-plus-render, and layout stability.
  • Batch geometry reads, then style writes.
  • Animate transform and opacity, not width, height, or top.
  • Keep the DOM small. Virtualize long lists. Simple selectors reduce style cost.
  • Remember the main thread runs JS, style, and layout. Long tasks drop frames.

One model is enough: bytes to DOM and CSSOM, then render tree, layout, paint, composite. Optimize the stage you are actually waiting on.

FAQ

What is the critical rendering path?

The work a browser does to turn HTML, CSS, and JavaScript into pixels: DOM, CSSOM, render tree, layout, paint, and composite.

How is the render tree different from the DOM?

The DOM holds every document node. The render tree holds only nodes needed to draw, with computed styles. display:none nodes stay in the DOM but leave the render tree.

Why does CSS block first paint?

A late rule can change any element. Painting before CSS finishes would flash unstyled content, then relayout.

Why do script tags pause HTML parsing?

Classic scripts may change the document. defer, async, and modules change when scripts run.

What is the difference between reflow and repaint?

Reflow recalculates geometry. Repaint redraws pixels. A color change is often a repaint. A width change is both.

How does the GPU help?

Compositing and some raster work can run on the GPU. Style and layout still run on the main thread.

What causes layout shift?

Images without reserved space, webfonts that change metrics, injected banners, and DOM insertions above existing content.

Does HTTP/3 change rendering?

No. It can deliver CSS and scripts faster. The renderer still parses, lays out, paints, and composites.

Related Articles

Next Post Previous Post