pretext · under the hood

An interactive exploration of how pure-JS text measurement works using a simplified version of Pretext — from raw string to pixel-accurate line heights, without ever touching the DOM.

The Pipeline

Pretext splits text layout into a one-time prepare() phase and a near-free layout() phase. Here's every stage your text passes through:

📝
Input
Raw string
🧹
Normalize
Collapse WS
✂️
Segment
Intl.Segmenter
🧲
Merge
Glue rules
📐
Measure
Canvas widths
📏
Layout
Pure math
Verify
vs. DOM

Your Text

Type anything, or pick a preset that exercises a different part of the engine. The entire pipeline re-runs live as you edit.

Whitespace Normalization

CSS white-space: normal collapses runs of spaces, tabs, and newlines into a single space, then trims leading/trailing whitespace. This is the first thing Pretext does — before any segmentation.

Before → After

Word Segmentation

The browser's built-in Intl.Segmenter splits text into word-like and non-word-like segments. This handles CJK (per-character), Thai (no spaces between words), Arabic, and other scripts correctly — something regex can never do reliably.

Raw Intl.Segmenter Output

Segment Merging & Glue Rules

Raw segments aren't enough. Punctuation like "better." must stay glued to its word (browsers measure them together). Opening quotes attach forward. CJK characters get split into individual graphemes for per-character line breaking. This is where 80% of the language-specific logic lives.

Merged Segments (what actually gets measured)

Canvas Measurement

Each merged segment is measured once via canvas.measureText() — the same font shaping engine the browser uses for layout, but without triggering DOM reflow. Results are cached per (segment, font) pair. This is the key trick that makes everything else possible.

Segment Widths (px)

Line Breaking — Pure Arithmetic

Now the hot path: walk the cached widths, accumulate along each line, and break when the next segment would overflow maxWidth. Trailing spaces "hang" past the edge (matching CSS). This runs in ~0.0002ms — drag the slider and watch it reflow instantly.

400px

Verification vs. Real DOM

The ultimate test: does our arithmetic match what the browser actually renders? We create a hidden DOM element with the same text, font, width, and CSS rules, measure its height, and compare. The green result below is live — computed right now in your browser.

Pretext (canvas + math)
Browser DOM (ground truth)