Three days ago, Cheng Lou quietly dropped a library called Pretext. By “quietly” I mean the internet immediately caught fire. Here’s why, and what happened when I actually used it.
The Problem You Didn’t Know Was Ruining Your Site
Every time your browser needs to know how tall a paragraph is — for a dynamic layout, a chat bubble, a masonry grid, anything — it does something violent. It triggers a layout reflow: a full recalculation of the position and size of every visible element on the page. One measurement, one reflow. Five hundred text blocks? Five hundred reflows. This is the single biggest source of jank on the web, and it’s been the only option since the ’90s.
Pretext sidesteps all of it. The key insight is that canvas.measureText() taps into the browser’s own font shaping engine but operates completely outside the layout tree. Measure the character widths once through canvas, cache them, and from that point on, text layout becomes pure arithmetic. No DOM. No reflow. Just math.
The numbers are not subtle: 500 text blocks measured through the DOM takes 15–30ms and triggers 500 reflows. Pretext does it in 0.05ms with zero reflows. That’s 300–600x faster. The whole library is 15KB.
What Pretext Actually Gives You
The API is refreshingly small. Two paths depending on what you need:
Path 1 — Just give me the height. You call prepare() once with your text and font string, then call layout() with a max width and line height. It returns the total height and line count. Pure math, instant result. This alone unlocks proper virtualized lists without guesswork, layout-shift-free content loading, and CLS scores you can actually be proud of.
Path 2 — Give me the lines and let me place them. Use prepareWithSegments() instead, then choose your adventure: layoutWithLines() for all lines at a fixed width, layoutNextLine() for variable-width layouts where each line can be different (text flowing around an image, for example), or walkLineRanges() when you want to binary-search for the optimal container width without even building line strings. This is the path that enables rendering to Canvas, SVG, WebGL — anything.
The language support is comprehensive. Latin, CJK, Arabic (with bidi), emoji, mixed scripts — it handles them all correctly, including browser-specific quirks that would take you weeks to debug on your own.
I Put It in My WordPress Theme. Here’s What Happened.
I’d been fighting with a dynamic text section in my theme — a testimonial area where quotes of different lengths needed to lay out into a masonry-style grid without the horrible content-jumping you get when the browser recalculates heights after render. The old approach used getBoundingClientRect() in a ResizeObserver callback, and every resize triggered a cascade of reflows that you could feel on mobile.
Swapping in Pretext took surprisingly little effort. I loaded it via npm, called prepare() for each testimonial text block on init, and then on resize I just re-run layout() with the new container width. No DOM reads. The heights come back instantly and I set them as CSS custom properties. The masonry grid now resizes without a single frame of jank.
The part that impressed me most: on prepare(), there’s a one-time cost of about 19ms for a large batch of 500 texts (my theme has maybe 6–12 testimonials, so it’s imperceptible). After that, layout() runs in under 0.1ms for the entire batch. On every window resize. The ResizeObserver callback went from “please don’t drag the browser edge” to genuinely smooth.
The Dragon Demo Is Not a Gimmick
Go look at the demos page. The headline one is an 80-segment dragon that follows your cursor while an entire page of text reflows around it in real time. Every frame, the library recalculates which lines of text need to part around the dragon’s body, carves out horizontal exclusion zones, and fills the remaining slots with text — at 60fps, with zero DOM measurements.
The aiia.ro team built their own version and wrote honestly about the four failed attempts before they landed on the text-reflow approach: a particle field that blobbed into unreadable smears, a character grid that was just noise, a matrix rain with broken canvas layering, and a destructive dragon that demolished the page before anyone could read it. The winning version works because the dragon and the text coexist — the words move aside and come back, which is the whole philosophical point of the library. Text as a participant in the composition, not a static block.
Other demos worth your time: the Bubbles demo that shrink-wraps multiline chat messages to their tightest possible width (using walkLineRanges() to binary-search the optimal container — something that’s literally been missing from the web), the Masonry demo where card heights are predicted without any DOM reads, and the Editorial Engine with animated orbs, pull quotes, and multi-column flow.
Who Should Care
If you build any of the following, Pretext is probably relevant to you right now: virtualized lists or feeds with variable-height text items, masonry or Pinterest-style layouts, chat interfaces with dynamically sized bubbles, editorial or magazine-style layouts, SVG text rendering (since SVG’s <text> element still doesn’t support line wrapping, 23 years later), server-side PDF or image generation that involves text, or anything where CLS is killing your Core Web Vitals score.
Cheng Lou built this using Claude Code and Codex, running them for weeks to match browser-level accuracy across languages and edge cases. He explicitly said the API is designed to be “AI-friendly” — meaning you can hand it to an AI coding assistant and get working demos fast. Having tried it myself, I’d agree: the surface area is tiny and the naming is intuitive.
The Bottom Line
Pretext is one of those rare libraries where the pitch sounds too good (“300x faster text measurement!”) and then you use it and it’s actually underselling itself. The speed is the headline, but the real shift is what it enables: layouts that were previously impossible at interactive frame rates, text that participates in dynamic compositions instead of sitting in a static box, and a future where measuring text on the web doesn’t require asking the browser to stop everything and think.
npm install @chenglou/pretext. It’s 15KB, MIT-licensed, zero dependencies. Go play with it.
Top Reference Links
- Pretext GitHub Repository — Source code, API docs, and benchmarks https://github.com/chenglou/pretext
- Pretext Live Demos — Accordion, Bubbles, Dragon, Editorial Engine, Masonry, and more https://chenglou.me/pretext/
- Cheng Lou’s Launch Post on X/Twitter — The original announcement in his own words https://x.com/_chenglou/status/2037715519277760531
- VectoSolve Deep Dive — Performance benchmarks, SVG use cases, and technical breakdown https://vectosolve.com/blog/pretext-svg-text-layout-300x-faster-2026
- aiia.ro Dragon Demo & Writeup — Honest build log including four failed attempts before the text-reflow breakthrough https://aiia.ro/blog/cheng-lou-launches-pretext-javascript-library-multiline-text-measurement/
- Hacker News Discussion — Community reactions, technical Q&A, and edge case discussions https://news.ycombinator.com/item?id=47556290
- Paul Irish’s “What Forces Layout/Reflow” — The definitive reference on why DOM measurement is expensive (the problem Pretext solves) https://gist.github.com/paulirish/5d52fb081b3570c81e3a
- npm Package Page — Installation, version history, and download stats https://www.npmjs.com/package/@chenglou/pretext
- web.dev — Avoid Large Complex Layouts and Layout Thrashing — Google’s own documentation on the reflow problem https://web.dev/avoid-large-complex-layouts-and-layout-thrashing/
- Chrome UX Report (CrUX) — Core Web Vitals data showing how widespread CLS issues are across the web https://developer.chrome.com/docs/crux/
Leave a Comment