Lines0
Columns0
Layout0.0ms
Canvas rendering, pretext layout

The Quiet Revolution in Web Typography


When Johannes Gutenberg pulled the first proof from his press in Mainz around 1440, he established principles of typographic layout that would endure for half a millennium. Justified columns of text, carefully balanced margins, harmonious proportions between typeface and leading — these were not aesthetic preferences but engineering necessities, constraints born from the physics of movable type. Each line had to fill its measure exactly, or the forme would not lock properly in the chase. Justification was not a stylistic choice; it was structural. And so every newspaper column, every book page, every magazine spread for five hundred years was built on this foundation: text flowing precisely through a measured space, each line an expression of the tension between content and container.

The web abandoned nearly all of it. The first browsers rendered text in a single ragged column, with line breaks determined by whatever width the window happened to be. There was no justification, no multi-column flow, no text wrapping around images in the way a print designer would recognize. The web chose flexibility over typographic control, and for an entire generation designers accepted the tradeoff. CSS improved things incrementally — web fonts restored real typefaces, media queries enabled responsive layouts — but the fundamental constraint persisted. The browser owned text layout absolutely, and asking it for information about that layout was ruinously expensive.

Gutenberg Bible, detail — Mainz, c. 1455

The expense is measured in reflows. Every time a web application asks the browser how tall a paragraph is, or where its lines break, the browser must recalculate the position of every element on the page. A single measurement costs five to thirty milliseconds of main-thread time. When an application needs hundreds of measurements — for a virtualized message list, a masonry photo grid, an editorial page with text routing around images — the accumulated cost makes the interface unusable. Chrome's profiler flags it with angry red bars. Performance audits dock your score. But the developer has no alternative. CSS provides no mechanism for computing text dimensions without rendering the text into the DOM first.

"For thirty years, the browser has been the gatekeeper of text information — and it charged dearly for every answer."

CSS Shapes, finalized in 2014, was supposed to bridge the gap between print and screen. It allows text to flow around defined shapes: circles, polygons, even image alpha channels. On paper, it was the answer. In practice, it is remarkably constrained. Shapes only work with floated elements. Text wraps on a single side. The shape must be declared statically in CSS — you cannot animate it or update it dynamically without triggering the very reflows you were trying to escape. And critically, you get no access to the resulting geometry. Where each line begins, how many lines exist, what height the shaped block occupies — all hidden behind the layout engine.

What if text measurement did not require the DOM at all? The browser's canvas API includes a measureText method that returns the width of any string in any font, without triggering layout reflow. Canvas uses the same font engine as the DOM — the measurements are identical — but because it operates outside the layout tree, there is no reflow penalty. A library called Pretext exploits this asymmetry. It segments text using the browser's Intl.Segmenter, measures each segment once via canvas, and caches the widths. After this one-time preparation, all layout becomes pure arithmetic: walk the cached widths, track the running total, insert a line break when the sum exceeds the maximum.

Responsive editorial prototype, 2026

The approach handles every writing system the browser supports. Chinese characters break individually. Thai text splits at syllable boundaries. Arabic ligatures remain intact. Emoji grapheme clusters — including multi-codepoint sequences like family emoji — stay together as single units. A single preparation call handles all of this, returning a compact handle for relayout. From that point forward, computing line breaks at any width costs roughly two ten-thousandths of a millisecond. Fast enough to relayout an entire page on every frame of animation, every pixel of window resize, every keystroke in a live editor.

"When text measurement becomes free, the interfaces that existed only in print become interactive."

Every letter on this page was measured by Pretext, positioned by JavaScript, and rendered to canvas. The headline was sized through binary search: trying progressively larger fonts until finding the maximum that preserves whole words on each line. The body text is justified, with extra space distributed proportionally between words, each word's width known exactly from cached measurement. The columns reflow on every pixel of window resize. The drop cap is measured and positioned by the same engine, with subsequent lines wrapping beside it at a reduced width. Pull quotes and images sit as obstacles that the layout engine routes around, line by line, adjusting available width dynamically. Zero DOM reads throughout.

Gutenberg solved justification with lead spacers and a locking frame. Five centuries later, we solve it with arithmetic and a fifteen-kilobyte JavaScript library. The tools have changed beyond recognition, but the principles have not. Text wants to flow through measured spaces, to fill its column, to wrap around the obstacles placed in its path. For thirty years the web denied it this nature, not for lack of ambition but for lack of a fast path to the information. The canvas had the answer all along. We just had to stop asking the DOM.