What is Pretext, and why should React developers care?
A practical introduction — what problem Pretext solves, what the API looks like, and three production patterns where it saves frames.
20 interactive demos built on @chenglou/pretext — the 15KB zero-dependency TypeScript library by Cheng Lou (React core, ReasonML, Midjourney). Reflows, games, ASCII art, multi-script editorial layouts. Drag the panel on the right to see it work in real time.
Community-maintained, not an official site. The library lives at github.com/chenglou/pretext · official demos at chenglou.me/pretext.
Hand-picked from 20 community projects. Click any card to launch the live demo — they all run right here in the browser, no install.
Every community-built demo, browseable by category. Filter instantly — URL updates so you can share a deep link to any view.
All demos are open-source · submit yours via GitHub Discussions ↗
Every getBoundingClientRect(), every offsetHeight read inside a tight loop forces a synchronous browser reflow. In a virtual scroll, chat thread, or AI streaming UI, this is the silent killer of 60fps.
prepare()Runs once per text + font pair. Pretext segments your string using Unicode rules (Intl.Segmenter) and measures each segment's glyph width via Canvas.measureText(). Result is cached for the lifetime of the page.
Cost: 0.1–1ms depending on text length. Pay once, reuse forever.
layout()Pure arithmetic. Walks cached segment widths, tracks a running total, inserts line breaks where width is exceeded. No DOM. No reflow. Ever.
Cost: ~0.001ms per call. Fast enough to invoke thousands of times per frame — for virtual scrollers, chat UIs, animations, games.
offsetHeight back into JSprepare(text, font) oncelayout(handle, width) per rowNo build step required. Drop into any TypeScript or JavaScript project — works in Node, the browser, web workers, and inside React / Vue / Svelte / vanilla.
// 1 · install — npm i @chenglou/pretext import { prepare, layout } from '@chenglou/pretext' // 2 · measure once per text + font (cached for the rest of the page) const handle = prepare('Hello, Pretext. 你好,世界.', '16px Inter') // 3 · lay it out at any width — pure arithmetic, ~0.001ms const { height, lineCount, lines } = layout(handle, 400, 24) // 4 · reuse the handle for any other width — instant const narrow = layout(handle, 240, 24) // → 0.001ms const wide = layout(handle, 800, 24) // → 0.001ms
15KB gzipped · zero peer dependencies · TypeScript types included. ESM and CJS builds shipped side-by-side.
Pass your text and font spec. Pretext segments with Intl.Segmenter and measures via Canvas. The returned handle is reused forever.
Call layout(handle, width, lineHeight) as often as you want. Pure JS — safe inside requestAnimationFrame, web workers, or SSR.
Pretext was extracted from production interfaces — chat, virtual scroll, editorial flows, real-time dashboards. The community demos above are the wild branches; below are the boring, valuable ones.
Pre-compute heights for 10,000+ variable-height items without creating a single DOM element. Pairs naturally with React Virtuoso, TanStack Virtual, or any virtualizer.
Predict message bubble heights before the model finishes streaming. Tight-wrap to minimize whitespace. Eliminate the jumpy layout shift every AI chat suffers from.
CJK, Arabic, Hebrew, Thai, Korean — Pretext measures every script with the same two-function API. Unicode segmentation and bidi handled automatically.
Text flowing around obstacles, magazine layouts, ASCII art with precise glyph measurements — the community demos above prove what becomes possible with per-line control.
| Aspect | DOM measurement | Pretext |
|---|---|---|
| Speed per call | 0.5 – 2 ms (forced reflow) | ~0.001 ms (pure arithmetic) |
| DOM access | Creates hidden elements | Zero DOM reads / writes |
| Layout thrashing | Triggers browser reflow | Never — impossible by design |
| SSR / Web Workers | No — requires a browser | Yes — works in Node, workers, edge |
| Unicode & i18n | Depends on browser version | Intl.Segmenter — consistent everywhere |
| Bundle size | Browser built-in | ~15KB gzipped · 0 deps |
| Framework | Coupled to DOM lifecycle | Agnostic — React, Vue, Svelte, vanilla |
Data fetched live from the public GitHub API · falls back to a cached snapshot if rate-limited.
A practical introduction — what problem Pretext solves, what the API looks like, and three production patterns where it saves frames.
A teardown of a 40ms scroll jank bug we hunted down inside a Slack-style chat — replaced with Pretext in 30 lines of code.
A curated tour through the wildest community submissions — Bad Apple ASCII, dragon reflow, text physics, audio-driven typography.
A small, framework-friendly hook for measuring text without ever touching the DOM — pairs with Suspense and concurrent rendering.
中文开发者视角下的 Pretext —— 为什么它对 CJK 排版友好,如何处理混排、垂直书写和复杂段落。
An end-to-end walkthrough of building a community demo — scaffolding, layout, deploy, and submitting to pretext.cool.
Direct, hand-written reference content for the searches developers actually type. No filler, no thin pages.