How Pretext Eliminates DOM Reflows for Ultra‑Fast Text Measurement

Pretext, a zero‑DOM, high‑performance text measurement engine created by React core contributor chenglou, uses Canvas‑based calculations and a two‑stage prepare/layout workflow to avoid layout reflows, delivering up to 500× speed gains for virtual scrolling, rich‑text rendering, and AI‑driven UI layout predictions.

AI Architecture Path
AI Architecture Path
AI Architecture Path
How Pretext Eliminates DOM Reflows for Ultra‑Fast Text Measurement

Traditional text measurement in front‑end development renders strings into the DOM and reads dimensions via getBoundingClientRect or offsetHeight, which forces a layout reflow and causes jank when measuring thousands of items.

Pretext Library

Pretext is a pure JavaScript/TypeScript engine for text measurement and layout. It avoids DOM manipulation by using Canvas for width calculation and supports DOM, Canvas, and SVG rendering. The design is inspired by Sebastian Markbage’s text‑layout project and is planned to work in server‑side environments.

Core Implementation

DOM‑free measurement : Canvas measures text width without creating DOM nodes, eliminating reflows.

Two‑stage workflow : prepare normalizes, tokenizes and segments the text once; layout performs only arithmetic on the cached data.

Full language support : Handles CJK, RTL, Emoji and bidirectional text out of the box.

Performance Characteristics

Zero reflow : No DOM operations, so measurement count is not limited by layout cost.

Benchmark : Preparing 500 text blocks takes ~19 ms; laying them out takes ~0.09 ms, roughly 500× faster than DOM‑based methods.

Cacheable results : Layout output can be cached, providing deterministic dimensions and avoiding layout shift.

Key API Usage

Basic measurement:

import { prepare, layout } from '@chenglou/pretext';
const prepared = prepare('AGI spring is here', '16px Inter');
const { height, lineCount } = layout(prepared, 300, 20);

Preserve whitespace (e.g., for textarea):

const prepared = prepare(textareaValue, '16px Inter', { whiteSpace: 'pre-wrap' });
const { height } = layout(prepared, textareaWidth, 20);

Custom line‑by‑line layout:

import { prepareWithSegments, layoutNextLine } from '@chenglou/pretext';
const prepared = prepareWithSegments('Long text', '18px Helvetica Neue');
let cursor = { segmentIndex: 0, graphemeIndex: 0 };
let y = 0;
while (true) {
  const width = y < image.bottom ? columnWidth - image.width : columnWidth;
  const line = layoutNextLine(prepared, cursor, width);
  if (!line) break;
  ctx.fillText(line.text, 0, y);
  cursor = line.end;
  y += 26;
}

Utility functions:

import { clearCache, setLocale } from '@chenglou/pretext';
clearCache(); // free memory
setLocale('zh-CN'); // set language locale

Installation & Quick Start

npm install @chenglou/pretext
# optional local demo
git clone https://github.com/chenglou/pretext
cd pretext
bun install
bun start

Project repository: https://github.com/chenglou/pretext

Typical Use Cases

High‑performance virtual scrolling or infinite lists

Rich‑text and complex custom layouts

AI‑generated UI layout predictions

Cross‑Canvas/SVG rendering

Server‑side text layout calculations

Practical Recommendations

Integrate Pretext early in virtual‑scroll implementations.

Reuse the result of prepare across multiple layout passes.

Call clearCache when switching fonts or after large batches to manage memory.

Keep CSS font and line-height values in sync with the parameters passed to Pretext for accurate measurements.

Performance optimizationvirtual scrollingtext measurementPretext
AI Architecture Path
Written by

AI Architecture Path

Focused on AI open-source practice, sharing AI news, tools, technologies, learning resources, and GitHub projects.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.