Pretext: Measuring Text Without the DOM
How a 30-year browser problem met a 15KB TypeScript library -- and why 31,000 developers starred it in 25 days.
Timeline
- Mid-1990s The problem begins
Web developers discover there is no reliable way to measure text dimensions before it hits the DOM. Synchronous layout reflow becomes an accepted cost.
- 2015 react-motion ships
Cheng Lou publishes react-motion, replacing CSS transitions with physics-based springs. Same instinct as Pretext: replace a browser primitive with a userland implementation.
- Pre-2026 Canvas insight emerges
Sebastian Markbage (React core team) demonstrates that Canvas measureText() accesses the font engine without triggering DOM reflow. Cheng Lou explores the idea in a text-layout prototype.
- March 2026 Pretext ships
Cheng Lou publishes Pretext: seven source files, ~15KB of TypeScript, two-phase measurement and layout. 31,000 GitHub stars in 25 days.
- March 2026 Community response
380-point Hacker News thread. Substantive discussion of Safari rendering discrepancies, canvas-vs-DOM accuracy tradeoffs, and real-world use cases in text editors and data visualization.
- 2026-03-31 Native ports begin
swift-pretextkit released by Tornike Gomareli, bringing Pretext to macOS and iOS. Five days from browser library to native platform port.
The Problem Is Older Than Most Web Developers
There is a question that comes up whenever you build anything with text that needs to be measured before it is rendered: how wide will this string be?
CSS can answer it, but only after the string hits the DOM. The browser measures text during layout. Ask for that measurement before layout and the browser has to stop, run layout, measure, and hand you the number. This is a synchronous layout reflow. It is not a bug or a performance footgun you can avoid with careful coding — it is how the model works. The DOM is the font engine's output, not its input.
The consequence is that any application needing to know text dimensions before rendering is stuck in a loop: render first, measure what rendered, then adjust. Do that 500 times in a frame and you are paying 30ms or more in layout reflow cost alone, before you have shown the user anything.
This is not a new observation. Web developers have been working around it since the mid-1990s. The workarounds are all variations on the same theme: estimate, pre-render offscreen, batch, or avoid the problem entirely by constraining your layout so that you never need to measure. None of them are clean. They are compromises with the rendering model.
Who Cheng Lou Is, and Why That Matters
In March 2026, Cheng Lou published Pretext, a TypeScript library that measures text without touching the DOM. By any metric the reception was extraordinary: 31,000 GitHub stars in 25 days, a 380-point thread on Hacker News, coverage from HackerNoon to Chinese tech press. But the why behind the reception has as much to do with who built it as with what it does.
Cheng Lou is not primarily known as a text layout researcher. He is known for react-motion, a library he published in 2015 that replaced CSS transitions and the then-dominant react-tween-state approach with physics-based spring animations. react-motion now has 21,700+ stars and was influential enough to shape how the React ecosystem thinks about animation. The insight behind it was similar to Pretext in structure: the native browser primitive (CSS transitions) was too constrained to express what developers actually needed, so the right move was to implement the behavior in userland where you had full control.
After react-motion, Lou spent several years at Facebook working on ReasonML and ReScript — an effort to bring ML-family type systems and semantics to the JavaScript ecosystem. His 2016 React Europe talk, "On the Spectrum of Abstraction," remains one of the more precise articulations of a philosophy he has returned to across different projects: reducing expressivity through the right constraints yields more capability, not less. A primitive that does one thing with precision is more powerful than a general tool that approximates many things.
When Lou publishes a library, the community pays attention. Pretext benefited from that credibility, but it also had to hold up under the scrutiny that comes with it. It did.
The Insight: Canvas as Font Engine Proxy
The core technical idea in Pretext is not new. Sebastian Markbage, a member of the React core team, had established the central insight in an earlier prototype: the Canvas API's measureText() method gives you access to the browser's font engine without triggering a DOM layout reflow.
measureText() is a Canvas method that takes a string and returns a TextMetrics object containing width (and in modern browsers, additional metrics). It uses the font configuration set on the Canvas 2D context. Critically, it does not require the string to exist in the DOM, and calling it does not trigger layout reflow. It is a direct call to the font measurement subsystem.
Lou had explored this direction in an earlier project called text-layout. Pretext is the production-quality result of that exploration, incorporating AI-assisted development to handle the hardest parts of the problem: browser inconsistencies across rendering engines, scripts, and font configurations.
The limitation is real and worth stating clearly: Canvas measureText() and actual DOM rendering can diverge. Subpixel rounding differences, font fallback chain resolution differences, and rendering-engine-specific behavior mean that Pretext's output is a high-fidelity approximation, not a guaranteed match to what the browser will render. The Pretext RESEARCH.md documents these discrepancies honestly.
The Two-Phase Architecture
The design that makes Pretext practically useful is not just the Canvas insight — it is the separation of measurement from layout.
Most text measurement approaches, if they avoid DOM reflow at all, do it by batching: collect all your measurement requests, run them in one pass, then proceed. Batching is better than one-at-a-time, but the measurement cost is still paid on every layout pass. If you are re-laying out the same text with different container widths (responsive design, resizable panels), you pay the Canvas measurement cost each time.
Pretext introduces a two-phase split:
Phase 1: prepare() takes a text string and a font configuration and runs the expensive work: Unicode segmentation via Intl.Segmenter, Canvas measurement of each segment, and storage of the results in a two-level cache keyed by font string and segment text. This is the only phase that touches Canvas. It is paid once per unique (text, font) pair.
Phase 2: layout() takes the prepared text object and a container width and returns line break positions and character offsets. It does this with pure arithmetic on the cached widths from Phase 1. No DOM access. No Canvas calls. No side effects. The measured performance is approximately 0.0002ms per block.
The consequence is that if you need to lay out the same text at ten different container widths, you call prepare() once and layout() ten times. The expensive work is amortized.
AI-Assisted Development at the Core
Pretext was built AI-in-the-loop in a way that was integral to getting the hard parts right, not an afterthought.
The hardest problem in building a text measurement library is not the algorithm — it is building the ground truth. What does the browser actually do with this string, at this font size, on this platform, in this rendering engine? The answer varies across Chrome, Firefox, and Safari in ways that are not always documented and not always consistent with the CSS specification.
Lou trained Claude and Codex on browser ground truth data collected across widths and scripts, then built automated verifier loops that compared Pretext's output against actual browser rendering. The test data in test-data.ts reflects this process: it is not hand-authored fixture data, it is a distillation of browser behavior captured and verified programmatically.
The result is a test suite (layout.test.ts, 36KB) that is larger than most of the implementation files it covers. That ratio is intentional.
The Platform Argument
In thoughts.md, Lou articulates something beyond the immediate library: CSS was designed around a specific set of text layout primitives. Those primitives are narrow enough that new layout patterns — the kind needed for rich text editors, design tools, canvas-based applications, collaborative documents — require either new browser specifications or degraded implementations built on top of existing primitives.
Expanding what is possible in userland, even at the cost of some accuracy relative to the native implementation, is better for the web ecosystem in the long run. It creates existence proofs for new primitives, surfaces the specific places where browser APIs need to improve, and lets developers ship things that would otherwise wait years for standardization.
Pretext is a bet that accurate-enough text measurement in userland unblocks a category of applications that the DOM model currently forecloses.
The Reception and What It Signals
The Hacker News thread (380 points, 70 comments) was substantive. The top comments engaged with the Safari rendering discrepancy, the canvas-vs-DOM accuracy tradeoffs, and whether the performance gains justified the measurement divergence. Several developers reported using the library against concrete problems: rich text editors, data visualization labels, custom layout engines.
That pattern — a specific technical solution to a known problem, an honest RESEARCH.md documenting the limitations, an author with credibility in the space and a track record of following through — is what 31,000 stars in 25 days looks like when the stars are real.
Beyond the Browser
Five days after Pretext launched, the ports started. Tornike Gomareli released swift-pretextkit, a native Swift port that brings Pretext's two-phase text measurement to macOS and iOS apps. Gomareli claims the approach halves CPU and power usage compared to other options in the Apple ecosystem.
The speed of this port says something about the architecture. Pretext's core insight -- separate expensive measurement from cheap layout, cache aggressively -- is not tied to the browser's Canvas API. It is a general pattern for text layout that works anywhere you have a font engine and need to know where lines break. The TypeScript implementation is one expression of the idea. Swift is another. Rust, C++, and others will follow if the pattern holds.
For a deeper analysis of where Pretext fits in the broader landscape, see Pretext, and What's Next.
Sources
- chenglou/pretext GitHub repository: thoughts.md, RESEARCH.md, source files
- Cheng Lou, "On the Spectrum of Abstraction," React Europe 2016
- chenglou/react-motion GitHub repository
- Hacker News thread on Pretext (2026)
- HackerNoon coverage of Pretext (2026)
- Sebastian Markbage, earlier Canvas measureText prototype (referenced in Pretext documentation)
- swift-pretextkit -- Swift port by Tornike Gomareli
- Tornike Gomareli on X -- swift-pretextkit announcement
- Pretext, and What's Next -- Cyrus Radfar
Ready to explore the code?
Start the Pretext tour