做前端开发的都知道,多行文本的高度测量一直是个头疼的问题。传统做法要么用 getBoundingClientRect,要么靠 offsetHeight,这些都会触发浏览器的重排(layout reflow),性能开销相当大。
今天要介绍的 Pretext 这个开源库,就是来解决这个痛点的——它能精确测量多行文本的高度和布局,而且完全不碰 DOM,纯靠 Canvas 和数学计算搞定。

Pretext 的核心原理很有意思:它借用浏览器自己的字体引擎作为”ground truth”,通过 Canvas 的 measureText 来做文本测量,然后用纯数学方式计算行数和高度。这样既能保证测量精度,又能避免 DOM 操作带来的性能损耗。
31.8k 的 Stars 摆在这儿,说明确实有两把刷子。
相关链接
- GitHub 仓库:https://github.com/chenglou/pretext
- 在线 Demo:https://chenglou.me/pretext/
- npm 安装:
npm install @chenglou/pretext
Pretext 是什么
Pretext 是一个纯 JavaScript/TypeScript 编写的多行文本测量与布局库。它的核心价值在于:在不触碰 DOM 的情况下,精确计算出多行文本的高度、行数,甚至每一行的具体内容。
作者是 chenglou,MIT 协议开源,目前已经斩获了 31,872 Stars 和 1,649 Forks,妥妥的明星项目。
这个库的设计思路受到了 Sebastian Markbage 十年前的项目 text-layout 启发,在此基础上发展出了更完善的架构。
核心功能
Pretext 提供了两套 API,满足不同的使用场景:
1. 快速测量文本高度(不碰 DOM)
这是最常用的场景。你只需要调用 prepare() 做一次预处理,然后反复调用 layout() 获取高度:
import { prepare, layout } from "@chenglou/pretext"
const prepared = prepare("AGI 春天到了. 시작했다 journey 🚀", "16px Inter")
const { height, lineCount } = layout(prepared, textWidth, 20)
性能数据:
prepare()单次处理 500 条文本约 19mslayout()热路径每次仅需 0.09ms
如果你需要支持 Textarea 风格的文本(保留空格、Tab、换行),可以传入 { whiteSpace: "pre-wrap" } 选项:
const prepared = prepare(textareaValue, "16px Inter", { whiteSpace: "pre-wrap" })
const { height } = layout(prepared, textareaWidth, 20)
2. 手动控制每一行的布局
换用 prepareWithSegments API,你可以逐行获取文本内容,甚至动态改变每行的宽度:
import { prepareWithSegments, layoutWithLines } from "@chenglou/pretext"
const prepared = prepareWithSegments("AGI 春天到了. 시작했다 journey 🚀", "18px \"Helvetica Neue\"")
const { lines } = layoutWithLines(prepared, 320, 26)
for (let i = 0; i < lines.length; i++) {
ctx.fillText(lines[i].text, 0, i * 26)
}
更高级的玩法是 walkLineRanges(),它只返回每行的宽度和光标位置,不构建完整的文本字符串,非常适合做二进制搜索宽度、shrink-wrap 布局等高级操作。
还有 layoutNextLine(),支持动态宽度——这在文字环绕浮动元素(如图片)的场景下特别有用:
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 === null) break
ctx.fillText(line.text, 0, y)
cursor = line.end
y += 26
}
应用场景
Pretext 的价值在于解锁了一些以前很难实现的 Web UI 能力:
- 虚拟滚动/可视区域渲染:不用再靠估算或缓存来预测列表项高度,可以精确计算
- 瀑布流/Masonry 布局:纯 JS 实现的灵活布局,不再依赖 CSS
- 防止布局抖动(CLS):文字加载前就能预留精确高度,滚动位置不会跳
- 无浏览器环境的文本验证:特别是现在 AI 代码生成场景,可以验证按钮标签会不会溢出
- Canvas/SVG/WebGL 渲染:手动控制每一行的绘制,适配各种自定义渲染需求
快速部署
安装
npm install @chenglou/pretext
# 或者
bun add @chenglou/pretext
运行 Demo
git clone https://github.com/chenglou/pretext.git
cd pretext
bun install
bun start
# 然后打开 /demos(注意不要加末尾斜杠)
注意事项
Pretext 并非要做一个完整的字体渲染引擎,它目前针对的是常见的文本场景:
white-space: normalword-break: normaloverflow-wrap: break-wordline-break: auto
另外,system-ui 字体在 macOS 上可能导致 layout() 精度问题,建议使用具体的字体名称。
适用人群
- 前端开发:需要精确文本测量来优化性能的工程师
- UI 库开发者:正在构建虚拟列表、瀑布流等复杂布局的开发者
- Canvas/WebGL 开发者:需要在画布上渲染文本的工程师
- AI 代码生成场景:需要无浏览器环境验证文本布局的开发者
总结
Pretext 解决的是一个看似小但实际很关键的问题——多行文本的精确测量。通过预计算 + 纯数学热路径的思路,它实现了又快又准的文本布局能力。
31.8k Stars、1.6k Forks 的数据说明社区对这类工具确实有强需求。如果你也在被文本高度计算折磨,不妨试试 Pretext,说不定就打开新世界了。
© 版权声明
本站部分内容源于网络收集,文章等版权归原作者所有,若需删稿请联系管理员邮箱:[email protected]
相关文章
暂无评论...