← markvrma chenglou/pretext ↗

unre­flowed.

Five experiments in setting type without asking the DOM how big it is. Every line on this page is computed by pretext, then drawn — sixty times a second.

II

Pour

layoutNextLineRange() · one call per slot · any shape

Text is a liquid if you can ask for one line at a time at any width. Each frame a silhouette is rasterised, sliced into horizontal slots, and pretext fills every slot in reading order. Hover to carve a hole; the paragraph flows around the wound.

III

Shrinkwrap

walkLineRanges() · binary search · the width CSS can't give you

Once a bubble wraps, width: fit-content snaps to the full max-width and leaves a ragged gutter. The hatching on the left is that gutter, drawn from pretext's own line widths. On the right, a binary search finds the narrowest width that keeps the same number of lines.

CSS · fit-content
pretext · shrinkwrapped
300px
IV

The height oracle

prepare() + layout() · vs. offsetHeight · an evaluation

I spend my days evaluating models, so here is one more. Pretext predicts the rendered height of a paragraph from arithmetic alone. The browser supplies ground truth the slow way: it renders the paragraph and we read offsetHeight. Every dot is one paragraph at a random width and size. The diagonal marks a perfect prediction.

exact match
predicted = actual, to the px
mean abs error
px, across all samples
pretext layout()
hot path, no DOM
DOM reflow
write style → read offsetHeight
worst sample
Run the eval to see the hardest paragraph.
samples are drawn from my CV; fonts are Fraunces at 13–19px
V

Shatter & reflow

layoutWithLines() · every word is a body · reflow gets animated

CSS reflow teleports. Here, because the lines are known before anything is drawn, every word gets a target position and a spring to reach it. Drag the dashed edge to resize the column. Drop the paragraph, then put it back.