展示 HN:使用字体度量预测文本高度的 React Hooks,在渲染之前计算。

2作者: ahmadparizaad7 天前原帖
我创建了 @pretext-studio/core 来解决一个特定的问题:浏览器在渲染之前不会告诉你文本块的高度。这迫使你进入一个先渲染再测量的循环(这会导致布局偏移),或者使用像 max-height: 9999px 这样的技巧来实现手风琴动画(这使得缓动效果看起来不正确,因为动画运行的高度是 9999px,而不是实际内容的高度)。 这个库封装了 @chenglou/pretext,一个纯 JavaScript 的文本布局引擎,它使用通过字体度量 API 一次性加载的字体度量来复制浏览器的换行算法。从那时起,计算高度变得简单——不需要 DOM,不需要 getBoundingClientRect,也不需要重排。prepare() 调用大约耗时 0.03 毫秒;layout() 调用耗时不到 0.01 毫秒。结果被缓存到模块级的 LRU 映射中,因此对相同字体/大小对的重复调用几乎是免费的。 主要的钩子包括 useTextLayout(在给定宽度下获取一个块的高度和行数)、useBubbleMetrics(找到保持行数的最紧凑宽度,这消除了 CSS fit-content 带来的空白空间)和 useStableList(在绘制之前预计算一组项目的高度,对于虚拟列表和砖石布局非常有用)。还有一个 MeasuredText 组件,带有调试覆盖层,可以在实际渲染的文本上绘制预测的行边界,以便你可以看到预测与实际的差异。 诚实的限制是:它仅适用于可以加载度量的字体,因此任意系统字体或表现不佳的可变字体可能会出现偏差。每个钩子的 isReady 标志在字体度量加载之前都是 false,因此在使用网络字体时需要根据它来控制渲染。它目前也不支持 white-space: pre-wrap。欢迎反馈——特别是如果你遇到字体加载或非拉丁脚本的边缘案例。 GitHub: <a href="https://github.com/ahmadparizaad/pretext-studio-core" rel="nofollow">https://github.com/ahmadparizaad/pretext-studio-core</a> — npm: @pretext-studio/core
查看原文
I built @pretext-studio&#x2F;core to solve a specific annoyance: the browser won&#x27;t tell you how tall a text block is until after it renders. This forces you into either a render-then-measure cycle (which causes layout shift) or hacks like max-height: 9999px for accordion animations (which makes easing look wrong because the animation runs over 9999px, not the actual content height).<p>The library wraps @chenglou&#x2F;pretext, a pure-JS text layout engine that replicates the browser&#x27;s line-breaking. algorithm using font metrics loaded once via the Font Metrics API. From there, computing height is arithmetic — no DOM, no getBoundingClientRect, no reflow. A prepare() call runs in ~0.03ms; a layout() call in under 0.01ms. Results are cached in a module-level LRU map so repeated calls for the same font&#x2F;size pair are nearly free.<p>The main hooks are useTextLayout (height + line count for a block at a given width), useBubbleMetrics (finds the tightest width that preserves line count, which eliminates the dead space you get from CSS fit-content), and useStableList (pre-computes heights for a list of items before paint, useful for virtualized lists and masonry layouts). There&#x27;s also a MeasuredText drop-in component with a debug overlay that draws predicted line boundaries over actual rendered text so you can see where predictions diverge.<p>The honest limitation: it only works with fonts you can load metrics for, so arbitrary system fonts or poorly-behaved variable fonts may drift. The isReady flag on every hook is false until font metrics load, so you need to gate renders on it when using web fonts. It also doesn&#x27;t handle white-space: pre-wrap yet. Feedback welcome — especially if you&#x27;ve hit edge cases with font loading or non-Latin scripts.<p>GitHub: <a href="https:&#x2F;&#x2F;github.com&#x2F;ahmadparizaad&#x2F;pretext-studio-core" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;ahmadparizaad&#x2F;pretext-studio-core</a> — npm: @pretext-studio&#x2F;core