CHAPTER 10 – How HTML Works
Checking engine…

10.1 — The Rendering Pipeline Sequence & Speculative Optimization

To the browser, your HTML arrives as a stream of raw bytes – blind electrical pulses. Turning those pulses into an interactive, painted page requires a multi‑phase pipeline operating at millisecond speed. Understanding this pipeline is the foundation of advanced performance engineering.

High‑level diagram showing Bytes → Characters → Tokens → DOM Tree → Layout → Paint
Figure 10.1: The complete rendering pipeline – from network bytes to painted pixels.

Phase 1: Conversion – Bytes to Characters

The browser receives a memory buffer filled with raw bytes (octets). For example, < is 0x3C, h is 0x68, 1 is 0x31, and > is 0x3E. These hexadecimal numbers are meaningless on their own.

The conversion phase reads the binary data and decodes it into a linear stream of characters according to a character encoding ruleset – almost always UTF‑8. The engine determines the encoding by checking, in order:

  1. The Byte Order Mark (BOM) at the very start of the file.
  2. The Content‑Type HTTP header sent by the server.
  3. An early <meta charset="..."> tag in the document.

Once the encoding is identified, the bytes are translated into a continuous string of characters – the raw material for the next phase.

Diagram showing raw bytes like 0x3C, 0x68 being decoded into characters like <, h
Figure 10.2: Conversion – binary octets decoded to characters using UTF‑8.

Speculative Optimization: The Preload Scanner

While the main HTML parser works sequentially, it can be blocked by synchronous scripts or stylesheets. To avoid wasting network time, modern browsers deploy a preload scanner (speculative parser) on a secondary thread.

The preload scanner does not build the DOM. Its sole mission is to scan ahead through the character stream and look for src, href, or other resource‑requesting attributes. When it finds them, it dispatches speculative network requests immediately, bypassing the main thread’s blocks. By the time the main parser resumes, critical stylesheets, fonts, and images are already in the cache.

Diagram showing main parser blocked by a script while the preload scanner fetches images and styles in parallel
Figure 10.3: The preload scanner runs in the background while the main thread is blocked.

Phase 2: Tokenization (Lexical Analysis)

Tokenization transforms the flat character stream into a sequence of structured tokens – discrete units of meaning like start‑tags, end‑tags, comments, and text. This is performed by a state machine defined in the HTML specification.

The state machine consumes characters one at a time, switching between internal states:

  • Data state – reading ordinary text characters.
  • When it encounters <, it transitions to the tag open state.
  • If the next character is an ASCII letter, it moves to tag name state and collects the element name until a space, /, or > is found. On > it emits a start tag token.
  • If a / immediately follows the <, it moves to the end tag open state, eventually emitting an end tag token.
  • Other transitions handle attributes, comments, DOCTYPEs, and raw text elements.

The output is a linear stream of tokens, ready for hierarchical construction.

State machine diagram showing transitions from data state through tag open, tag name, and back to data state
Figure 10.4: The lexical tokenizer's state machine, simplified for illustration.

Phase 3: Tree Construction – Building the DOM

Tokens are flat; the DOM is a nested tree. The tree constructor uses a stack of open elements to track nesting depth and build parent‑child relationships.

When a start tag token arrives:

  1. A new element node is created in memory.
  2. The constructor looks at the node currently on top of the stack and attaches the new node as its child.
  3. The new node is pushed onto the stack, making it the current context for subsequent tokens.

When an end tag token arrives, the element is popped off the stack, and the context returns to its parent.

This push‑and‑pop mechanism ensures that every text character and child element is appended to the correct parent, resulting in a perfectly structured DOM tree – the live document representation.

Diagram showing stack of open elements growing as start tags are processed and shrinking with end tags
Figure 10.5: The stack of open elements during DOM construction – push on start, pop on end.
TAKEAWAY

The rendering pipeline is a finely‑tuned sequence: bytes are decoded to characters, characters are tokenized by a state machine, and tokens are assembled into the DOM tree via a stack‑based constructor. Meanwhile, the preload scanner fires off network requests in the background to keep the pipeline fed. Grasping this flow empowers you to write HTML that loads instantly and renders without jank.

Checking engine…