Pretext Text Effects
Generate browser pages powered by Pretext (@chenglou/pretext)—a pure-arithmetic text measurement library that bypasses DOM layout reflow entirely. Pretext measures text with proportional font precision using canvas measureText, enabling effects impossible with CSS alone.
Companion library: opentype.js (opentype.js@1.3.4) — direct font binary parsing for per-glyph SVG path rendering, Bezier control point access, kerning tables, and variable font axes. Pretext handles line breaking; opentype.js handles what happens inside each glyph. Together they unlock effects neither can achieve alone.
Output is always a single self-contained HTML file. No build step, no framework, runs in any modern browser.
Quick Start
Describe a text effect. Claude picks the right Pretext pattern and generates a complete HTML file.
Examples:
/pretext fluid smoke ASCII art with gold characters on black/pretext chat bubbles that shrinkwrap tighter than CSS/pretext calligram — the word "ocean" shaped like a wave/pretext editorial layout with text flowing around draggable circles/pretext masonry grid of shower thoughts with instant height prediction/pretext glyph path art — SVG letterforms with stroke animation/pretext animated dragon cursor that pushes text aside as it moves/pretext illuminated manuscript with live vine growth reflow/pretext variable font wave — per-character weight animation/pretext glyph morph — letterform interpolation from A to Z/pretext letterbox gallery of "BEACON" in Playfair Display italic on dark background/pretext glyph-mask calligram — letter R filled with lorem ipsum in Georgia
Do NOT Use This Skill When
- Simple CSS
text-shadow,text-stroke, or gradient text effects - CSS Shapes level 1 (
shape-outsideon floated elements) for static layouts - Basic
@keyframestext animation (fade, slide, typewriter) - Monospace ASCII art (no proportional measurement needed)
- SVG
<text>without per-glyph control - Rich text editing (
contenteditable, ProseMirror, TipTap) - PDF generation or markdown rendering
These are all achievable without Pretext or opentype.js.
Effect Categories
Pretext-Only Effects
| Category | Pretext APIs Used | When to Use |
|---|---|---|
| Height Prediction | prepare + layout | Accordion, masonry, virtualized lists — anywhere you need text height without DOM reads |
| Shrinkwrap | walkLineRanges + binary search | Chat bubbles, tooltips, labels — finding the exact tightest width for multiline text |
| Obstacle Routing | layoutNextLine (variable width) | Text flowing around images, logos, draggable orbs — editorial layouts |
| Animated Obstacles | layoutNextLine + carveTextLineSlots | Moving creatures/orbs that displace text at 60fps — slot-carving fills BOTH sides of obstacle |
| Typographic ASCII | prepareWithSegments (char measurement) | Fluid simulations, 3D wireframes, particle systems rendered as proportional characters |
| Calligrams | prepareWithSegments + SDF | Words rendered as shapes using their own letters — hearts, stars, spirals |
| Glyph-Mask Calligrams | Canvas measureText + getImageData pixel mask | Any font glyph as calligram shape — fill a large letter with small text using pixel-mask technique (no SDF needed, no opentype.js) |
| Letterbox Gallery | Glyph-mask + per-letter <canvas> grid | Each character in a string gets its own canvas with text fill, cursor displacement, and independent interaction |
| Multi-column Editorial | All rich APIs combined | Magazine-style layouts with headline fitting, pull quotes, drop caps, column flow |
Pretext + opentype.js Effects
| Category | APIs Used | When to Use |
|---|---|---|
| Glyph Path Art | opentype glyph.getPath() | SVG letterforms with fill/stroke/control point modes, stroke-draw animation |
| Text on Path | opentype getPath() + arc-length sampling | Per-glyph placement along Bezier curves with tangent rotation |
| Variable Font Animation | opentype font.tables.fvar.axes + CSS font-variation-settings | Per-character weight/width waves, breathe, ripple, cascade effects |
| Glyph Morphing | opentype paths + flubber interpolate() | Letterform interpolation between glyphs with contour-aware morphing |
| Outline Calligrams | Pretext layoutNextLine + opentype glyph mask | Text fills the interior of a large glyph's actual contour (not SDF approximation) |
| Illuminated Manuscript | All Pretext + opentype combined | Living medieval pages: wet ink, vine reflow, capital inflation, aging, erasure poetry |
Concept-to-Effect
Every design decision derives from the concept. Do not default—derive.
Choose the API tier from the effect complexity:
- Static height only →
prepare()+layout()(fastest, opaque) - Need line text/positions →
prepareWithSegments()+layoutWithLines() - Need per-line width variation →
layoutNextLine()(iterator, variable width per line) - Need aggregate geometry without strings →
walkLineRanges()(no string materialization) - Need individual character widths →
prepareWithSegments()on single chars
Choose the rendering target from the output type:
- DOM elements (
.line { position: absolute }) → editorial, accordion, masonry - Canvas 2D (
ctx.fillText) → calligrams, some ASCII art - HTML spans with inline styles → typographic ASCII (weight/style/opacity per character)
Architecture
Pretext CDN → prepare/prepareWithSegments → layout/layoutNextLine → line positions
↓
opentype.js CDN → font.parse(buffer) → glyph.getPath() ──────────> SVG <path> elements
↓
requestAnimationFrame (if animated)
resize handler (always)
Two-library split: Pretext decides WHERE text goes (line breaking, obstacle routing). opentype.js decides HOW each glyph looks (SVG paths, Bezier curves, contour data). Use Pretext alone for DOM-positioned text. Add opentype.js when you need per-glyph SVG rendering, path animation, or glyph contour access.
CDN Imports
<!-- Pretext (ESM, required) -->
<script type="module">
import { prepare, layout, prepareWithSegments, layoutWithLines, walkLineRanges, layoutNextLine, clearCache } from 'https://esm.sh/@chenglou/pretext@0.0.2'
</script>
<!-- opentype.js (UMD, optional — only for glyph path effects) -->
<script src="https://cdn.jsdelivr.net/npm/opentype.js@1.3.4/dist/opentype.min.js"></script>
<!-- Font binary for opentype.js (Inter .woff — confirmed working) -->
<!-- const FONT_URL = 'https://cdn.jsdelivr.net/npm/@fontsource/inter@5.0.8/files/inter-latin-400-normal.woff' -->
<!-- flubber (optional — only for glyph morphing) -->
<!-- <script src="https://cdn.jsdelivr.net/npm/flubber@0.4.2/build/flubber.min.js"></script> -->
Import only the functions you need. Pin the version. opentype.js cannot parse .woff2 — use .woff or .ttf only.
Composition Parameters
All Effects
| Parameter | Default | Notes |
|---|---|---|
| Font | '18px Georgia, Palatino, serif' | Never use system-ui — unreliable with Pretext |
| Line height | 28 (px) | Must match CSS line-height for height prediction |
| Background | #08080e or #f5f1ea | Dark or light — never pure black #000 |
Typographic ASCII
| Parameter | Range | Default |
|---|---|---|
| Font size | 10–18px | 14 |
| Font family | serif preferred | Georgia, Palatino, "Times New Roman", serif |
| Charset | printable ASCII | .,:;!+-=*#@%&a-zA-Z0-9 |
| Weights | 1–3 | [300, 500, 800] |
| Styles | normal, italic | both |
| Opacity levels | 6–10 | 10 |