npm install @chenglou/pretext

Text measurement without touching the DOM

Pretext is a pure TypeScript text layout library that bypasses browser layout reflow, computing text height and line breaks with pure math. 300-600x faster than DOM-based measurement, with full support for multilingual text, emoji, and bidirectional text — built for the Canvas / SVG / WebGL era.

Text layout and measurement have always been the last and biggest bottleneck in unlocking more interesting UIs — especially in the AI era.

— Cheng Lou, creator of Pretext
10k+
GitHub Stars
0.0002ms
Per layout() call
300-600x
Faster than DOM
5KB
Gzipped size

Installation & Usage

$ npm install @chenglou/pretext
Basic usageTypeScript
import { prepare, layout } from '@chenglou/pretext';
 
// Step 1: Analyze font once (1-5ms, runs once)
const prepared = await prepare('Hello, 世界 🌍', '16px Inter');
 
// Step 2: Compute layout at any width (0.0002ms, call freely)
const { height, lineCount } = layout(prepared, 300);
 
console.log(height);     // Exact pixel height
console.log(lineCount);  // Number of lines

Pretext supports both ESM and CJS. Works in browsers, Node.js, and Web Workers.

Community Showcase

Creative demos that went viral on X / Twitter, showing what Pretext makes possible

The Web Is Interesting Again

@EsotericCofe

"finally the web has become interesting again"

The Little Illuminated Dragon

@Riyvir

"This little illuminated dragon is very happy about Pretext."

The Most Magical Time of My Life

@reathchris

"i am in the most magical time of my life"

Text Layout of My Dreams

@rauchg

"I can finally ship the text layout of my dreams"

Fluid Interfaces FTW

@vamsibatchuk

"this is gold. fluid interfaces ftw."

Your Physics Textbook Is Not Boring Anymore

@stevibe

"your physics textbook is not boring anymore"

Craaazy Water Ripple Effect

@dushankas

"craaazy"

Let’s Go! Play Pretext Breaker

@singular_prism

"Lets go! Play pretext breaker 🎮"

Why Pretext?

Every call to getBoundingClientRect() or offsetHeight forces the browser to pause all JavaScript execution and recalculate the entire page's geometry before returning a number. For a page with 500 text blocks, DOM-based measurement takes 15–30ms and triggers 500 layout reflows. Pretext completes the same task in 0.05ms with zero reflows — a 300-600x improvement.

Traditional approach

Create invisible DOM element → apply CSS → insert into document → call getBoundingClientRect() → remove element. Every measurement forces a full page layout reflow. 500 text blocks = 500 reflows.

Pretext approach

prepare() uses Canvas measureText to analyze font metrics once and cache them. Every layout() call after that is pure arithmetic — no DOM access, no reflow, callable from anywhere including Web Workers and the server.

Virtual Scrolling

Know exact item heights before rendering. Pretext removes estimation and post-render measurement for zero-error virtualized lists.

Prevent Layout Shift

Pre-compute layout with Pretext during SSR. Content loads without jumping, bringing CLS to zero.

Canvas / WebGL Rendering

Pretext delivers precise text layout without a DOM, enabling 60fps text animations, creative visual effects, and game scenes.

Masonry Layouts

Calculate card heights without DOM reads. Pretext moves layout computation ahead of the render phase.

Obstacle-aware Text Flow

With Pretext, text reflows around animated shapes in real time — an 80-segment creature moves through a page at 60fps while text continuously wraps around it.

SVG / Server-side Rendering

Combine Pretext with opentype.js to convert text to SVG paths server-side, generating vector typography with zero font dependencies.

How It Works

A two-phase Pretext design that separates expensive measurement from cheap computation

01

prepare() — One-time font analysis

Pretext first normalizes whitespace per CSS spec, then uses the browser's built-in Intl.Segmenter for Unicode segmentation — correctly handling CJK per-character line breaks, spaceless Thai, Arabic RTL scripts, and emoji sequences. Segmented units are then measured via Canvas measureText and cached by (segment, font) key. The entire prepare() phase takes 1–5ms and runs just once.

02

layout() — Pure arithmetic

With cached font metrics, every Pretext layout() call is pure math: walk through cached segment widths, accumulate until maxWidth is reached, break to a new line. Handles the CSS edge case where trailing spaces extend past the line width without causing reflowing. Each call takes ~0.0002ms — safe to invoke every animation frame.

03

Safari emoji calibration

Safari's Canvas API reports emoji widths that differ from actual DOM rendering. When Pretext first encounters emoji for a given font, it performs one hidden DOM measurement to establish a correction factor, caches it, and applies it to all subsequent emoji measurements — ensuring pixel-perfect accuracy across all browsers.

04

Built-in verification

Pretext includes a verification system that creates hidden DOM elements and compares their actual rendered height against Pretext's calculated values. This side-by-side comparison is what backs Pretext's accuracy claims and lets developers validate results in debug mode.

Supported Text Types

CJK (Chinese / Japanese / Korean)

Pretext applies per-character line breaking for CJK scripts, correctly handling boundaries with Latin text

Emoji

Full Unicode emoji sequences, skin-tone modifiers, ZWJ sequences — accurate across all browsers

Bidirectional text (BiDi)

Pretext preserves correct line-breaking and width calculation for mixed RTL Arabic/Hebrew and LTR text

Spaceless scripts

Thai and similar languages without inter-word spaces, relying on Intl.Segmenter for correct segmentation

Soft hyphens

Smart word-breaking with ­ soft hyphen support, with correct kerning rules between segments

Rich inline elements

Pretext supports mixed layout with inline code blocks, links, chips, and other non-text elements flowing within text

Comparison with Alternatives

Pretext isn't the only text measurement approach, but it leads in the combination of speed, accuracy, and language support

DOM measurement

Triggers layout reflow. 500 text blocks = 15–30ms + 500 reflows

Raw Canvas.measureText

Requires building your own line-breaking, segmentation, and emoji correction

HarfBuzz (WASM)

Professional shaping engine, but large WASM binary adds significant bundle overhead

Pretext

0.0002ms/call, 5KB gzip, Intl.Segmenter + Canvas combination

About the Author

Cheng Lou

Cheng Lou

@chenglou

Former React core team member, co-creator of ReasonML (now Melange), and current frontend engineer at Midjourney. The development of Pretext itself is notable: Cheng Lou provided browser rendering benchmarks to AI coding assistants like Claude Code and Codex, which then iteratively tested and optimized the implementation across key container widths over several weeks. After validating Pretext's reliability in Midjourney's production environment, he open-sourced it.

Community Reception

After launching in March 2026, Pretext sparked immediate discussion across the frontend community

Text layout and measurement have always been the last and biggest bottleneck in unlocking more interesting UIs — especially in the AI era.

Pretext solves the long-standing problem of calculating line-wrapped text height outside the DOM.

This isn't a flashy demo — it's foundational infrastructure for replacing CSS-based layout. A real UI paradigm shift.

16M
Tweet impressions at launch
10k+
GitHub Stars in one week
Dozens
Media outlets covered it

Known Limitations

Pretext isn't a silver bullet — understand these boundaries before adopting it

Requires Canvas API

Pretext needs Canvas support and cannot run in pure text terminals or Canvas-free rendering environments. All modern browsers support Canvas, so this is rarely a practical concern.

Fonts must be loaded first

Fonts must be fully loaded before calling prepare(). If you're using Web Fonts, use font-display: block or wait for font.load() to resolve before calling Pretext.

prepare() has initial overhead

The first Pretext prepare() call takes 1–5ms (potentially longer for very large text blocks). Run it asynchronously during the data-loading phase, not on the critical render path.

Standard CSS line-breaking only

Pretext targets white-space: normal + word-break: normal + overflow-wrap: break-word + line-break: auto. It does not currently cover pre-wrap or other non-standard wrapping modes.