CSS 中为特定字符设置不同字体

为追求更好的阅读体验,本站的中文文章采用了混合字体的排版方式。例如在 Windows 环境中,中文字符以 Microsoft Yahei 渲染,而英文字符则使用 Open Sans 渲染。由于 Microsoft Yahei 中也包含英文字符的字形,其在 font-family 中的优先级需排在 Open Sans 后面,从而保证 Open Sans 能够正确渲染英文字符。大致的代码如下:

[lang="zh"] {
font-family: "Open Sans", "Microsoft Yahei", var(--font-fallback);
}

但这种方式有一个问题,即标点符号的字形比较难看。具体而言是弯引号 U+201C U+201D ,它们的字形无论在 Microsoft Yahei 或是 Open Sans 中都是半角宽度,且头部和尾部粗细区分不明显,难以辨别前后。反观宋体 SimSun 的呈现则更为清晰,更符合中文排版的习惯。

那是否可以在 CSS 中为特定字符设置不同字体呢?答案是肯定的。为此我们要在宋体的基础上“改进”出一种新字体,不妨命名为 SimSun-PuncSimSun-Punc 只用于渲染 U+201CU+201D 两个字符,其余字符则正常回落至 Microsoft YaheiOpen Sans

[lang="zh"] {
font-family: "SimSun-Punc", "Open Sans", "Microsoft Yahei", var(--font-fallback);
}

SimSun-Punc 又该怎么定义呢?难道需要根据 SimSun.ttf Subset 出一个新字体文件吗?其实不然,我们可以使用 CSS 的 @font-face 规则,将 SimSun 作为基础字体,再通过 unicode-range 属性限定字符范围,从而实现“改进”字体的效果:

@font-face {
font-family: "SimSun-Punc";
src: local("SimSun");
unicode-range: U+201C-201D;
}

unicode-range 属性可用于设置 font-face 所应用的 Unicode 字符范围,这里我们指定了 U+201CU+201D 两个字符,如此一来便只有这两个字符会使用 SimSun-Punc 字体,从而达到预期的效果。


作者:hsfzxjy
链接:
许可:CC BY-NC-ND 4.0.
著作权归作者所有。本文不允许被用作商业用途,非商业转载请注明出处。

«新增域名 monad.run

OOPS!

A comment box should be right here...But it was gone due to network issues :-(If you want to leave comments, make sure you have access to disqus.com.