ENZH

Pretext: The Missing Layer Web Developers Have Been Waiting 30 Years For

📊 Slides

Last week Cheng Lou — the engineer behind React Motion, ReScript, and now at Midjourney — released pretext. Within 72 hours it had 13,000 GitHub stars.

That alone isn't remarkable. Open source projects go viral for lots of reasons. What's remarkable is what pretext does: it gives web developers something that iOS, Android, and Flutter have had as a one-liner for over a decade.

It tells you how tall text will be. Without touching the DOM.

The Problem Nobody Talks About

Here's something every frontend developer knows but rarely articulates: if you want to know how much vertical space a paragraph will take, the web gives you exactly one option. Insert the text into the DOM. Force the browser to recompute layout for the entire document tree. Read the result. Remove the element if you don't need it.

That measurement triggers a layout reflow — one of the most expensive operations a browser performs. And it's not local. CSS layout is globally coupled. Changing one element can cascade across the entire page.

Now imagine you're building a virtual list — a chat app, a social feed, an email client. You need heights for hundreds of items you haven't rendered yet. Each measurement forces a full reflow. The result is what Paul Irish documented as the "forced synchronous layout" problem: your app stutters, drops frames, and feels sluggish.

Compare this to iOS:

label.sizeThatFits(CGSize(width: 300, height: .greatestFiniteMagnitude))

One line. No side effects. No global recomputation. The layout engine is an independently queryable module.

Android has StaticLayout. Flutter has TextPainter. Jetpack Compose has TextMeasurer. Every major native platform treats text measurement as a standalone operation.

The web never did. And that decision, made in 1994 when CSS was designed for academic document exchange, became one of the longest-running architectural debts in software.

What Pretext Actually Does

Pretext exploits a backdoor: canvas.measureText(). The canvas API and DOM rendering share the same underlying font engine, but canvas operates completely outside the layout tree. Measuring text via canvas never triggers reflow.

The library works in two phases:

Cold path (once): prepare(text, font) segments the text using Intl.Segmenter for locale-aware word boundaries — handling CJK, bidirectional text, emoji, soft hyphens — measures each segment via canvas, and caches the widths. About 19ms for 500 texts.

Hot path (cheap): layout(prepared, maxWidth, lineHeight) runs pure arithmetic over cached widths, emulating the browser's word-wrap algorithm. Returns { height, lineCount }. No DOM access. About 0.09ms for 500 texts. That's a 200x speedup on the resize path.

The accuracy was validated by rendering the full text of The Great Gatsby across Chrome, Safari, and Firefox, then comparing pixel-by-pixel against pretext's predictions. The test corpus extends to public domain documents in Thai, Chinese, Korean, Japanese, and Arabic.

Why This Matters Beyond Performance

Performance is the obvious win. But the deeper impact is what pretext unlocks:

True virtualization. Virtual lists currently guess item heights or measure-then-render (causing visible jumps). Pretext lets you know every item's exact height before it enters the viewport. Zero layout shift.

Multiline shrink-wrap. CSS has no way to say "make this container exactly as wide as its widest line." Chat bubbles, labels, badges — they're all wider than they need to be. Pretext's walkLineRanges() binary-searches for the mathematically tightest width. This is a layout primitive the web literally cannot express.

Text-around-obstacle layouts. layoutNextLine() lets each line have a different max-width. Text flowing around images, shapes, or moving objects — the magazine layout CSS dropped for complexity — is now trivial in userland.

AI-friendly layout verification. Button labels don't overflow? Text fits the container? Pretext can verify this server-side, in CI, without a browser. This closes the loop for AI-generated UI iteration.

The Architectural Lesson

My friend yage wrote an excellent analysis framing pretext in terms of a broader design principle:

Good abstractions let you choose which layer to work at. Bad abstractions glue all layers together and give you no choice.

CSS chose to hide intermediate layout state. That looked clean in 1994. It's been accumulating interest for 30 years. The W3C knows — CSS Houdini's Font Metrics API was designed to fix this. As of 2026, no browser has implemented it. Pretext fills the gap in 15KB of userland JavaScript.

The parallel yage draws is sharp: this is the same architectural mistake we're making right now with AI systems. APIs that catch low-level errors and throw a clean "operation failed" protect human cognitive bandwidth. But when the consumer is an AI agent that needs try → feedback → correction loops, that same abstraction becomes an obstacle. The AI needs to observe intermediate state, not have it hidden behind a clean facade.

Pretext's architecture — an independent observation window alongside the existing system, not a replacement — is the pattern. Don't tear down the abstraction. Open a window on it.

The Demos Tell the Real Story

If you haven't seen the demos, stop reading and go look. The masonry layout runs 100,000 variable-height text items at 120fps. The editorial layout flows text around moving obstacles in real-time. The chat bubbles shrink-wrap perfectly — each one exactly as wide as its content, not a pixel more.

The community demos are equally impressive. pretext-explosive turns every character into a physics particle. illustrated-manuscript flows medieval text around an animated dragon.

These aren't just tech demos. They're UI patterns that were previously impossible — or at least prohibitively expensive — on the web.

The Vibe Coding Angle

One more thing. Pretext was built using what Cheng Lou calls "vibe coding" — Claude Code and OpenAI Codex as implementation engines, with Cheng Lou as the architect and quality oracle. He fed browsers' ground-truth rendering output to LLMs and had them iterate the TypeScript logic until it matched.

A genuinely hard engineering problem — cross-browser text layout with full internationalization — solved in weeks rather than years. The human provided the architectural insight and the validation methodology. The AI provided the implementation throughput.

That itself is a signal of where we're headed.


Pretext is at github.com/chenglou/pretext. yage's architectural analysis is at yage.ai/web-layout-tradeoff.html.

AI Field NotesPart 12 of 12
← PrevNext →

© Xingfan Xia 2024 - 2026 · CC BY-NC 4.0