不碰 DOM 就知道这段文字有多高——文本测量的 20 年难题,被一个纯 JS 库解干净了
更新于 2026-09-04
← 返回汇总文字有多高,算出来不问浏览器
纯 JS/TS 的多行文本测量与排版库:绕开 getBoundingClientRect 这类触发浏览器 reflow 的贵操作,自己实现断行逻辑,用浏览器 canvas 字体引擎做测量基准。一次 prepare 缓存好每个片段宽度,之后 layout 就是纯算术。支持 CJK、阿拉伯语 bidi、emoji、软连字符等「你都不知道存在」的语言特性。适合虚拟化列表、masonry、Canvas 排版、以及 AI 时代不开浏览器就验证文本 UI 的场景。作者 Cheng Lou(react-motion),架构源自 Sebastian Markbåge 的种子设计。
数据来源:GitHub API,采集于 2026-09-04。半年 50k stars 是现象级速度;MIT 协议;npm 包 @chenglou/pretext;尚无正式 release tag(活跃开发期)。
想知道一段文字在容器里折成几行、多高?唯一官方途径是把文字塞进 DOM 再量——触发 layout reflow,列表一长就是性能悬崖。
虚拟列表/masonry 需要提前知道每项高度。测不准就只能估高度 + 缓存 + 滚动跳位补偿——各种框架的滚动抖动问题根源都在这。
想在 canvas/WebGL 里排多行文字?浏览器只给你 measureText(单行宽度),断行、CJK、bidi 全要自己写——每个团队抄一份烂版本。
Pretext 的答案:断行逻辑自己实现(可控、可缓存),字宽测量借浏览器 canvas 字体引擎(不重造光栅化,天然和 CSS 渲染一致)。 measuring 变成纯算术——这就是它的全部秘密。
import { prepare, layout } from '@chenglou/pretext' const p = prepare( 'AGI 春天到了. بدأت الرحلة 🚀', '16px Inter') const { height, lineCount } = layout(p, 320, 20) // 纯算术,无 DOM 无 reflow
pre-wrap / word-break: keep-all / letter-spacing 均作为 prepare 选项对齐 CSS 行为。
const p = prepareWithSegments(text, font) const { lines } = layoutWithLines(p, 320, 26) lines.forEach((l, i) => ctx.fillText(l.text, 0, i * 26)) // 变宽排版:文字绕开浮动图片 const w = y < image.bottom ? colW - image.width : colW const r = layoutNextLineRange(p, cur, w)
walkLineRanges / measureLineStats 不分配字符串,专为二分搜索最优容器宽(shrink-wrap)设计——这个能力 web 平台一直没有。
-,没选中保持隐形prepare('AGI 春天到了. بدأت الرحلة 🚀',
'16px Inter')
中文 + 英文 + 阿拉伯语(RTL)+ emoji 混排一句话,这是文本测量库最难啃的凑齐款。
| 维度 | 评分 | 依据 |
|---|---|---|
| 问题价值 | reflow 是前端最贵操作,文本测量是虚拟化圣杯的最后一块 | |
| 方案优雅度 | 自实现断行 + 借浏览器字体引擎做基准,贵/便宜分离干净 | |
| 工程诚实度 | Caveats 清单 + PLATFORM_BUGS 台账,边界写得清清楚楚 | |
| 成熟度 | 半年新项目,无 release,API 仍在演进 | |
| 时代势能 | AI 生成 UI 的验证缺口正好被它补上,势能在自己脚下 |
综合 9/10。可能成为下一个「所有 UI 库默默依赖」的地基层——react-motion 作者的第二个 legend 作品正在发生。
亲手体验「纯算术测文字」:输入中英阿混合文本,拖宽度滑块,实时看到贪心断行的每一行、行数、最宽行与总高度——旁边同步渲染同款 DOM,肉眼对照精度。这正是 prepare→layout 两阶段在做的事。
进入 Playground →