Demos: https://chenglou.me/pretext/, https://somnai-dreams.github.io/pretext-demos/
https://kevinho.com/experiments/biomap/
Pretext: TypeScript library for multiline text measurement and layout
github.com
1–10 of 76 posts
Demos: https://chenglou.me/pretext/, https://somnai-dreams.github.io/pretext-demos/
https://kevinho.com/experiments/biomap/
Pretext: TypeScript library for multiline text measurement and layout
github.com
Problem: DOM-based text measurement (getBoundingClientRect, offsetHeight) forces synchronous layout reflow. When components independently measure text, each measurement triggers a reflow of the entire document. This creates read/write interleaving that can cost 30ms+ per frame for 500 text blocks.
Solution: two-phase measurement centered around canvas measureText.
prepare(text, font) — segments text via Intl.Segmenter, measures each word via canvas, caches widths, and does one cached DOM calibration read per font when emoji correction is needed. Call once when text first appears.
layout(prepared, maxWidth, lineHeight) — walks cached word widths with pure arithmetic to count lines and compute height. Call on every resize. ~0.0002ms per text.
Some details on how it works from a code comment: Problem: DOM-based text measurement (getBoundingClientRect, offsetHeight) forces synchronous layout reflow. When components independently measure text, each measurement triggers a reflow of the entire document. This creates read/write interleaving that can cost 30ms+ per frame for 500 text blocks. Solution: two-phase measurement centered around canvas measureText. pre…
Maybe for this we need a new web "Search" API instead of JS. Not sure it can be done otherwise without browser's help.
This is something I've been thinking for ages and would love to add to Ensō (enso.sonnet.io), purely because it would allow me to apply better caret transitions between the lines of text.
(I'm not gonna do that because I'm trying to keep it simple, but it's a strong temptation)
Now a CSS tangent: regarding the accordion example from the site (https://chenglou.me/pretext/accordion), this can be solved with pure CSS (and then perhaps a JS fallback) using the `interpolate-size` property.
https://www.joshwcomeau.com/snippets/html/interpolate-size/
Regarding the text bubbles problem (https://chenglou.me/pretext/bubbles), you can use `text-wrap: balance | pretty` to achieve the same result.
(`balance` IIRC evens out the # of lines)
Pretext makes this easier. Just pass the text and text properties (font, color, size, etc) into a pure JS API and it layouts the content into given viewport dimension.
Earlier you'll have to either use measureText or ship harbuzz to browser somehow. I guess pretext is not a technical breakthrough, just the right things assembled to make layouting as a pure JS API.
I have one question though: how is this different from Skia-wasm / Canvaskit? Skia already has sophisticated API to layout multiline text and it also is a pure algorithmic API.
Some details on how it works from a code comment: Problem: DOM-based text measurement (getBoundingClientRect, offsetHeight) forces synchronous layout reflow. When components independently measure text, each measurement triggers a reflow of the entire document. This creates read/write interleaving that can cost 30ms+ per frame for 500 text blocks. Solution: two-phase measurement centered around canvas measureText. pre…
What about hyphenization?
Quick overview of pretext: if you want to layout text on the web, you have to use canvas.measureText API and implement line-breaking / segmentation / RTL yourself. Pretext makes this easier. Just pass the text and text properties (font, color, size, etc) into a pure JS API and it layouts the content into given viewport dimension. Earlier you'll have to either use measureText or ship harbuzz to browser somehow. I gues…