Code of the Day
AdvancedBrowser Rendering

Parsing and the Render Tree

Before a pixel is painted, the browser parses HTML into the DOM and CSS into the CSSOM — then merges them into a render tree that contains only what will actually be painted.

Web FoundationsAdvanced8 min read
Recommended first
By the end of this lesson you will be able to:
  • Describe how the browser turns an HTML byte stream into a DOM tree
  • Explain what the CSSOM is and why CSS blocks rendering
  • Trace the path from DOM + CSSOM to a painted frame
  • Distinguish layout, paint, and compositing as separate pipeline steps

You have written HTML and CSS for a while. But what does the browser actually do between receiving the first byte and lighting up a pixel? The answer is a five-step pipeline, and knowing each step tells you exactly why certain performance techniques work and others do not.

Step 1 — parsing HTML into the DOM

The browser receives HTML as a raw byte stream. Its reads that stream from top to bottom, tokenising tags, attributes, and text content into nodes, and linking those nodes into a tree:

document
└── html
    ├── head
    │   ├── meta (charset)
    │   └── link (stylesheet)
    └── body
        ├── h1 "Hello"
        └── p  "World"

This tree is the . Every element, text node, and comment in your HTML becomes a node in it. JavaScript reads and modifies the DOM at runtime; the browser uses it as the source of truth for everything that follows.

One important detail: the parser is streaming. It does not wait for the entire file to arrive before building nodes — it builds as bytes arrive. That is why content higher in the HTML appears on screen sooner. It is also why a <script> tag in <head> can stall the process (more on that in the Critical Rendering Path lesson).

Step 2 — parsing CSS into the CSSOM

In parallel (or as soon as a <link rel="stylesheet"> is encountered), the browser fetches and parses your stylesheets. The output is the — a separate tree of style rules, one per selector, with inheritance and cascade already resolved:

body  → { font-family: sans-serif; color: #222 }
h1    → { font-size: 2rem; color: inherit }
p     → { margin-top: 1em }

Unlike the DOM, the CSSOM is not built incrementally. The browser must finish parsing all CSS before it can know the computed style of any element — because a rule in a later stylesheet can override an earlier one. This is the source of CSS's render-blocking behaviour: the browser will not proceed to the next step until every stylesheet has been downloaded and parsed.

An inline <style> block in <head> is available immediately — no network round-trip required. That is why inlining small amounts of critical CSS is a legitimate performance technique.

Step 3 — building the render tree

Once both trees exist, the browser merges them into the . The render tree keeps only what will actually be drawn:

  • Elements with display: none are excluded entirely (they take up no space and produce no pixels).
  • visibility: hidden elements are included — they occupy space but are drawn transparently.
  • Pseudo-elements like ::before and ::after are included even though they have no DOM node.

Each node in the render tree carries the fully computed style for that element: resolved font sizes, pixel values for lengths, final colours after cascade and inheritance.

Step 4 — layout

With the render tree built, the browser walks it and calculates the exact position and size of every box. This is called layout (or historically, reflow). The output is a set of coordinates: "this <h1> starts at (16, 80) and is 600px wide and 48px tall."

Layout is relative to the viewport, so it happens again whenever the window is resized, or whenever a DOM or style change affects geometry.

Step 5 — paint and compositing

Paint fills in the pixels — text glyphs, background colors, borders, box shadows, images. The browser may split the page into independent layers (a technique called promotion) and paint each layer separately.

then hands those layers to the GPU, which overlays them into the final image you see. Properties like transform and opacity live entirely on the compositor thread — they can be animated without touching the CPU's layout or paint steps.

Byte stream → DOM

            Stylesheet → CSSOM

            Render tree

             Layout

             Paint

           Compositing  →  pixels on screen

Where to go next

You now have a mental model of the full pipeline. Next: Reflow and Repaint — what happens when JavaScript or user interaction triggers a change mid-page, and why some changes are far more expensive than others.

Finished reading? Mark it complete to track your progress.

On this page