Demo · 02 · pretext playground

Measure text without touching DOM.

prepareWithSegments() does the one-time pass — segment, measure each token against canvas ground-truth, return an opaque handle. layoutWithLines() is pure arithmetic after that, safe to call every frame as the column width changes. No reflow, no getBoundingClientRect, no hidden measure-div.

Source · textarea edit to re-measure
Laid out · <canvas> no DOM text
column width · 440 px · drag to resize each tick = 50 px
find tightest width
width
line count
total height
widest forced line

What you're looking at

The textarea on the left is the source. Every keystroke re-runs prepareWithSegments(), which segments the text and measures each segment against a shared canvas context. That handle is cached until text or font changes.

The column on the right is rendered into a <canvas> — not a <div>. The orange handle sets max width; layoutWithLines(prepared, width, lineHeight) returns materialized line strings plus line count and total height by walking the cached segments. Pure arithmetic. Runs on every frame.

Tick shrinkwrap on: we binary-search the tightest width that still fits the paragraph in the line budget you set. Every probe is another measureLineStats() call — cheap because the segments were measured once.

@chenglou/pretext · /demos/playground/playground.ts