Pretext Text Measurement & Layout
Skill by ara.so — Daily 2026 Skills collection.
Pretext is a pure JavaScript/TypeScript library for fast, accurate, DOM-free multiline text measurement and layout. It avoids getBoundingClientRect and offsetHeight (which trigger expensive layout reflows) by implementing its own measurement logic using the browser's font engine as ground truth.
Installation
Core Concepts
prepare()/prepareWithSegments()— one-time analysis: normalize whitespace, segment text, measure via canvas. Cache and reuse this result.layout()/layoutWithLines()etc. — cheap hot path: pure arithmetic over cached widths. Call this on every resize, notprepare().- Font string format — same as
CanvasRenderingContext2D.font, e.g.'16px Inter','700 18px "Helvetica Neue"'.
Use Case 1: Measure Paragraph Height (No DOM)
With Pre-wrap (textarea-like)
With CJK keep-all
Use Case 2: Manual Line Layout
Get All Lines at Fixed Width
Line Stats Without Building Strings
Natural Width (No Wrap Constraint)
Variable-Width Layout (Text Around Floated Image)
Iterator API (Fixed Width, With Text Strings)
Use Case 3: Rich Inline Text Flow
For mixed fonts, chips, @mentions, and inline code spans:
Rich Inline Stats
Common Patterns
Virtualized List Row Heights
Binary Search for Balanced Text Width
Resize Handler Pattern
Prevent Layout Shift on Dynamic Content
API Quick Reference
Use Case 1 (Height Only)
Use Case 2 (Manual Layout)
Options
Troubleshooting
Text height is wrong / doesn't match browser rendering
- Ensure
fontstring exactly matches your CSSfontshorthand (weight, style, size, family all matter). - Ensure
lineHeightmatches your CSSline-heightin pixels. - Font must be loaded before calling
prepare()— usedocument.fonts.readyorFontFace.load().
prepare() is slow on every resize
- Only call
prepare()when text or font changes. For resizes, only calllayout()or equivalent.
Canvas not available (SSR / Node)
- Server-side support is listed as "coming soon". For now, this library requires a browser environment (canvas API).
CJK text not wrapping correctly
- Try
{ wordBreak: 'keep-all' }for Korean/Chinese text that should not break mid-word.
Rich inline items breaking when they should be atomic
- Add
break: 'never'to theRichInlineItemfor chips, mentions, badges.
Getting widest line for shrinkwrap containers
- Use
measureLineStats(prepared, maxWidth).maxLineWidthor walk withwalkLineRangesand track the maxline.width.


