中文 Letter Spacing

仅设置行间距不足以改善大段中文给人的那种密密麻麻一坨的呈现效果,一个理想的方案是将字间距设置到 0.05em 左右,不过会导致的另一个问题是英文的显示效果,例如我通常会选择的 Geist 字体。

这是一段 letter-spacing=0.05em 的英文: One's character is set at an early age, son. The choices you make now will affect you for the rest of your life. I hate to see you swim out so far you can't swim back.

这是一段 letter-spacing=0 的中文: 一个人的性格是在童年时代养成的,孩子。你现在作出的选择将会影响你的一生。我不想看到你走得太远,却又无法收场。

单独为中英文设置不同的 letter-spacing 属性并手动完成这件事是非常残忍的,当然也没人会在 Markdown 中这么做,不过幸好我们还是可以编写插件;这里要做的是在 hast 中添加插件,遍历节点,当一个元素节点中的文本内容完全为英文或字符时为该节点添加样式,否则解析子节点并重复以上工作,最终当节点是混合了中英文的文本节点时,将节点拆成文本节点+元素节点的组合,拆分工作可由正则表达式的 Groups 快速达成。

另外,对于如何判断字符是中文还是英文这件事的处理。起初想到的是使用比较通用的正则去匹配,后来注意到我正在使用的 @fontsource-variable/geist 提供了 unicode 的范围,让它进入正则就可以获得比较完美的匹配了。

最后设置整体的 letter-spacing 属性,子节点将被插件覆盖:

One's character is set at an early age, son. The choices you make now will affect you for the rest of your life. I hate to see you swim out so far you can't swim back.

一个人的性格是在童年时代养成的,孩子。你现在作出的选择将会影响你的一生。我不想看到你走得太远,却又无法收场。

摘自:怦然心动 - 第七章

CC BY-NC-SA 4.0 © Jiakun Zhao