本文讲解了字体回退(Font FallBack)的机制,它在字符无法在字体中找到对应的字形时发生。字体回退在网络排版中很常见,当浏览器无法加载指定字体时,会按照字体回退列表的顺序选择替代字体。这种机制在多语言和表情符号的排版中特别重要,因为不同的语言和表情符号需要特定的字形来呈现。然而,由于字符数量巨大,字体设计师无法绘制每个字符的字形,因此需要字体回退来处理。此外,本文还讨论了同形文字和替换字符在排版中的作用。最后,提到了字体回退可能带来的一些问题和解决方法。
如果您遇到过以下情况,
您收到了一条带有奇怪方框或问号的文本:
或者,您发送时 Emoji 看起来很好,但到达收件人时却被奇怪地分解了:
或者,您在 Twitter 上看到有人使用很酷的字体,而您却无法使用这些字体:
或者,你实际上想出了如何在 Twitter 上使用这些字体,结果却有人对你说他看到的是 "空盒子"。
或者,在一行中添加了一个表情符号 ,就在那一刻,文本行尴尬地向下移动:
**,时长00:09
或者,您向某人发送了非常酷的颜文字,结果却有人抱怨它看起来不太好:
这些变现可能会令人困惑。它们看起来像是渗透数字世界日常交互中的小错误。
但这些都不是错误,至少不是传统意义上的错误。所有这些例子都可以解释。它们有一个共同原因:一种重要的的数字排版机制。这种机制在字体中的字符无法覆盖时启用,我们称之为「字体回退(Font FallBack)」。
故意留出的空白
作为一名字体设计师,您的工作之一就是为您的字体提供所需的每个字形。
字形是一个印刷术语,它是指一个文字和它对应的形状。即使是简单的西文字体也有超过 200 个字形:26 个小写字母加上 26 个大写字母、10 个数字、符号、标点符号、重音符号。
**,时长00:15
Glyphs(字体应用程序)内的三种字体;注意 Hiragino Sans 的滚动条
当然,并非所有文字都是西方的。如果您正在为中文和日文书写进行设计,您的字形数量将达到数千个。任何字体都需要绘制字形。即使是较小的字体:符号和连字、深奥的标点符号、数字等。支持另一种书写系统会增加一整套字形,而且总是有另一种书写系统 —— 如果你支持拉丁语,为什么不覆盖整个西欧呢?那么中欧呢?然后是希腊语?然后是西里尔字母?还有越南语?
有些字体覆盖了字符中较少的数量,有些字体则覆盖了更多的字符
在某些时候,你必须划清界限。字体包总的最后一个字形。它有一个技术名称.notdef。它是最后手段的字形,当字体设计师绘制的文字没有覆盖到时使用该字形。
.notdef 是「字体回退」的原始版本,它是针对物理打印没有某个字形时基本解决方案。在金属活字的世界中,你不可能要求字体印刷活字中没有的字母。但计算机中文本显示成为字体和之间有种奇怪的转化。计算机可以显示其他人的文本,这些文本可能包换你的设备中不存在的字体。因此,你的字体文件需要告诉你:“我不知道这个特定的字符应该是什么样子。”
.notdef 通常看起来像一个简单的矩形,有时内部有十字架。这是 “空间故意留空” 的缩写。它不是一个具有特定代码的传统 Unicode 字符,而只是一个矩形,用来掩盖应该在那里的字符。当您复制并粘贴它时,它仍然是您想要看到的原始字符。毕竟,字体将来可能会更新更多的字形,或者您可以简单地切换到另一种支持该字符的字体:
**,时长00:06
.notdef 字形也是由字体设计者来绘制的。即使在矩形约定范围内,大小也会有所不同 - 一些类型设计师将矩形划掉,或者用问号装饰:
有些设计师放弃了绘制.notdef,选择什么也不做,让.notdef 成为一个空白方块。还有一些设计师绘制看起来有点疯狂的字形:
疯狂的例子很少见,但是常规的矩形呢?我们一生中已经多次看到这些矩形了。
然而,如果没有一个完整的隐形、令人印象深刻且独特的系统来覆盖每种字体,您可能会惊讶地发现它们的出现的频率会高得多。
「字体回退」
我们大多数人都熟悉的「字体回退」风格来自网络。它看起来像这样:
font-family: Joanna, Helvetica Now, Helvetica, Arial, sans-serif;
它的含义很简单:“要渲染此文本,请使用名为 Joanna 的字体。如果您没有,请使用 Helvetica Now。没有?请使用 Helvetica 怎么样?那些还没有吗?好吧,就使用 Arial 吧。没有 Arial 吗?只需使用系统推荐的任何通用无衬线字体即可。”
第一个字体通常是网络字体,与网站本身打包在一起。如果无法加载,那么接下来推荐的几种字体是那些已经在用户中流行的字体,或者是各种操作系统安装的默认字体。
第一种字体表现通常是完美的。每进一步后退,也是更大的妥协。你几乎可以看到一种趋势,将网页从一种独特的、完美匹配、代表品牌或情感的字体,转向越来越通用可靠的字体,当然,并不令人兴奋。
**,时长00:17
自 CSS 诞生之初,「字体回退」就一直存在,因为我们认识到,在我们的历史上,不存在每台计算机都使用同一组字体的情况。
除了字体列表之外,CSS 没有为「字体回退」提供更具体的控制:没有对大小、粗细或字母间距进行额外的调整。很遗憾地说,今天仍然没有。
但即使「字体回退」看起来陈旧且简单,您可能会对两件事感到惊讶:
第一,是它不是在字体级别运行,而是在字符级别运行。
第二,是你在 CSS 中声明的只是「字体回退」的一小部分。
字体作为漏网
在字符级别上操作意味着浏览器或操作系统会根据您要输入的每个文字重新访问您的「字体回退」表。如果前面的字体没有该字符,则会尝试列表中的另一种字体,依此类推。
让我们选择与上面相同的列表,稍微简化一下:
font-family: Joanna, Helvetica Now, Helvetica, Arial;
我电脑上的 Joanna 字体有 261 个字形,覆盖了一些字母。我没有 Helvetica Now,所以我们可以跳过它。传统的 Helvetica 字体有多达 2,252 个字形,其中包含西里尔文、格鲁吉亚文和越南文,以及大量数学和货币符号。Arial 甚至更多,它供了超过 3,300 个字形。
如果我要求浏览器使用上面的「字体回退」规则排版多语言句子,它将显示为:
这不是一个好看的句子,说明「字体回退」时控制有限。即使是较小的字体德语的表象都没有受到任何影响,但 Helvetica 的俄语和 Arial 的希伯来语则不太好:看起来太大、太粗。而波兰语的情况更糟,四分之一字的母退回到 Helvetica。
但话又说回来,这至少是一个可读的句子。
如果您对文本有绝对的控制权,您可以选择为每个单独的字符指定特殊字体来显示它,使一切看起来完美无缺。但你不必如此。因为在网络世界中,文本可以来自任何地方、任何时间。
**,时长00:06
在两种字体之间切换,每种字体都使用 Helvetica 作为后备字体
使用 Helvetica 和 Arial 等字体或其他包含数千种字形的流行字体仔细微调「字体回退」列表,这不仅是保留网站风格,也是确保覆盖范围。有时它帮助我将字体想象为漏网 —— 每个漏网都准备好捕获尽可能多的字母,但每个漏网本身也有很多漏洞。「字体回退」表允许下一个字体捕获前一个字体留下的字母,依此类推:
**,时长00:11
但您可能已经发现了:上面的「字体回退」表中列出的所有字体都不支持马拉雅拉姆语。也不包含任何表情符号。那么为什么这两个仍然呈现为有意义的字形,而不是豆腐呢?
实际上,在「字体回退」列表后面,您的浏览器或操作系统仍然会悄悄地添加十几种字体来帮助您,其中包括一些专门雅拉姆语、表情符号等创建的字体。
庞大的字形
如果 Arial 绘制超过 3300 个字符令人印象深刻,那么看看整个 Unicode 的范围就知道了。目前版本的管理着每个字符进行编码,其中包含超过 140,000 个字符。以后还会有更多。
与早期计算机难以处理 63、127 或 255 个字符相比,这是一个令人印象深刻的数字。但如果你知道到 Unicode 旨在涵盖 150 种不同的语言和数以万计的文字和符号(其中包括数百个箭头、数学符号、多米诺骨牌、炼金术和埃及象形文字和表情符号)。
对于字体设计师来说,绘制 140,000 个字形的任务将是残酷、疲惫且难以克服的。即使有人选择这样做,也会导致字体文件太大而无法加载。
但如果没有字体包含所有字符,那么寻找替代方案对于网页设计师来说就会变得痛苦。
好在您的操作系统和浏览器会执行此操作,因此您无需特意关注。他们通过对字体家族进行排列,并为你的「字体回退」表无法展示字符时兜底。
举个例子,我的 Mac 上的 4 种字体「字体回退」列表悄然扩展,看起来是这样:
font-family: Joanna, Helvetica Now, Helvetica, Arial, Menlo, Monaco, .AppleSymbolsFB, LucidaGrande, CourierNewPSMT, GeezaPro, NotoNastaliqUrdu, Ayuthaya,
Kailasa, PingFangSC, PingFangTC, HiraginoSans-W3, HiraginoSansGB-W3, PingFangHK, AppleSDGothicNeo, KohinoorBangla, KohinoorDevanagari, KohinoorGujarati,
MuktaMahee, NotoSansKannada, KhmerSangamMN, LaoSangamMN, MalayalamSangamMN, NotoSansMyanmar, NotoSansZawgyi, NotoSansOriya, SinhalaSangamMN, TamilSangamMN,
KohinoorTelugu, NotoSansArmenian, EuphemiaUCAS, STIXGeneral, Galvji, Kefa, .NotoSansUniversal, AppleColorEmoji, .LastResort;
Windows 的情况也类似:
font-family: Joanna, Helvetica Now, Helvetica, Arial, Tahoma, Segoe UI, Segoe UI Historic, Segoe UI Symbol, Segoe UI Emoji, Cambria Math, Abyssinica SIL,
DaunPehn, David, DokChampa, Ebrima, Estrangelo Edessa, Ethiopia Jiret, Gadugi, GF Zemen Unicode, Gulim, Han Nom A, Javanese Text, Lao UI, Leelawadee UI,
Kartika, Khmer UI, Malgun Gothic, Mangal, Meiryo, Microsoft New Tai Lue, Microsoft YaHei, Mongolian Baiti, MoolBoran, MS PGothic, Myanmar Text, Nirmala UI,
Nuosu SIL, Nyala, Phetsarath OT, Plantagenet, PMingLiU, Raavi, Saysettha OT, Shruti, Simsun, Sylfaen, Tunga, Visual Geez Unicode, Vrinda, WenQuanYi Zen Hei, Yu
Gothic, Arial Unicode MS, Code2000;
其中许多字体负责覆盖特定的语言(例如,NotoSansMyanmar 和 Myanmar Text 负责缅甸文字),而其他字体则有更具体的需求。Apple Symbols 可以帮助您处理从盲文、乐谱到 Apple 过去的古老符号的所有内容:
Apple Symbols 中的一些字形
另一方面,Segoe UI Historic 包含近 5,000 个古老的文字字形 —— 楔形文字、象形文字和帕提亚文字,虽然这些文字在纸张发明之前就消失了:
Segoe UI Historic 中的一些字形
还有一些字体负责处理所有表情符号 ——Mac 上的 AppleColorEmoji 和 Windows 上的 Segoe UI Emoji—— 与其他字体相比它们是独一无二的,因为它们是彩色的。
尽管我刚刚说过创建一种涵盖所有 Unicode 的字体会让人筋疲力尽且不可能,但一些字体设计者有足够的勇气去尝试这一点。例如 Arial Unicode、Unifont、Code2000 或 Noto 等字体,旨在成为最后一个漏网,展示尽可能多的剩余字符。
请注意,任何类似的图表本质上都是有缺陷的,因为比较字形计数与字符计数是一项挑战
这些字体是最后兜底字体,是「字体回退」底部最大的安全网:
两种兜底字体,帮助渲染文字
至此我们明白了浏览器渲染在句子时的情况 —— 所有字体都得到展示,最后两款字体提供了帮助:
换句话说,我们已经远离了.notdef 方块:
当只有几个字符丢失时,「字体回退」已经在十亿个简单的日常应用。我们可以通过「字体回退」实现这样的排版小奇迹,一句跨越百万年、百万公里的话:
我最喜欢的象形文字是𓁅𓅔𓀬,还有我最喜欢的楔形文字𒀼𒄭和𒋲,尽管我无法确定我更喜欢中国的冬天符号(冬),还是雪花( ❄️)…… 但可以作弊并选择一张同时具有这两者的麻将牌:🀩。
它让你您可以阅读这些内容。您还可以将复制并粘贴到文本编辑器中,甚至没有 CSS 的网站上…… 即使您对排版一无所知,这段文本的背后仍有 6 种不同的字体提供帮助。
当然,它们在视觉上可能不同,如果其中一个碰巧比其他的高,浏览器增加行高来容纳它。这就解释了为什么在输入表情符号是文本会被推高 —— 大部分字体不支持表情符号,因此它会退回到 Apple Color Emoji 这类字体,并且这类字体通常的比您正在使用的字体稍高。
**,时长00:10
回退到不同的字体,可能会改变字体基线
Hacks 和同形文字
在 140,000 个字符内,可能会出现一些视觉相似的文字。随着时间的推移,语言和文字以一种混乱的方式进化,它们没有总体规划的融合和发散。
英语中,人们也会将 O(字母)与 0(零)混淆。然后,西里尔字母的一部分看起来完全像拉丁语,而拉丁语的一部分可以假装它是希腊语。你可以创造性写出 “ОOO”,其中一个字母是拉丁文,一个是希腊文,一个是西里尔文。圆本身是一种通用形状,因此它在 Unicode 中一遍又一遍地出现:如 ◯、○、◌、𝗢、𝐎、𝖮、⚪、⥁ 等等,这样简单的形状还有更多。它们在印刷术中一个特殊的名称:同形文字(homoglyphs)。
另外,Unicode 还使用了一堆风格化的拉丁字母。许多来自数学,这些字母意有着不同的用途:运算符名称、常数、角度、变换、张量。它们单独包含在 Unicode 。毕竟,数学变量 𝑎 与向量 𝐚 不同,集合 𝔸 不应与矩阵 𝑨 混淆。
数学中不同字母表服务于特定原因的例子
使用者可以对字体有不同的理解。比如我可以不理解数学集合的情况下写 “𝕄𝕒𝕣𝕔𝕚𝕟”,仅仅是因为它看起来比 “Marcin” 更好。
同样,我可以在不了解数论的情况下写 “𝕸𝖆𝖗𝖈𝖎𝖓”,不打算求幂时写下 “ᴹᵃʳᶜⁱⁿ”,或者上演帽子戏法写下 “𝘔𝘢𝘳𝘤𝘪𝘯 𝙞𝙨 C⚪⚪L”,仅仅为了好玩。
许多字母看起来相似,这被 Unicode Text Converter 这类网站所利用,这类网站可以通过将你输入的字母替换成形状相近的 Unicode 字符。
以不同 “风格” 表达的 Figma 文字
如果你开始这样替换文字,那么也就离 把古字母「 ᴥ 」在捏成熊鼻子ʕ・ᴥ・ʔ ,或者用片假名组成耸肩表情 ¯(ツ)/¯ 就不远了。
这些玩法的排版在 Twitter 或 Facebook 这样的地方特别有用,这些地方实际上不允许您更改字体,甚至不允许使用粗体或斜体:
但这都是有代价的。计算机上看到的任何文本都不是仅供人眼使用的。经过 “重新设计” 的文本看起来很相似,但其实际含义可能截然不同。“𝕸𝖆𝖗𝖈𝖎𝖓” 通常无法使用搜索引擎找到。并且...... 它也会受到「字体回退」的变幻莫测的影响。
流行的字体都不包含数学符号或专门的字母。这些 “字体样式” 也会在 Unicode 的各个区块之间逐个字母地跳转。因此,它们中大多数将回退到系统深处的字体,并且不同平台上的回退字体千差万别,因此无法准确的知道这些字体在其他设备上如何显示。
**,时长00:06
在 macOS 和 Windows 中呈现的文本 “样式”
作为一名字体设计师,作为一个关心可访问性的人,我建议不要使用这些特殊 “字体”。
五种字体共同努力向您展示一个简单的翻桌表情符号,几个画框字符、2 个印度字符、1 个古代字符的、1 个日文字符和 1 个中文括号:
**,时长00:09
最后的手段
当角色穿过所有「字体回退」表并未被包涵时,某些平台会选择不绘制任何内容。其他平台将一路返回到.notdef 字符。
但也有其他方法。有些操作系统或浏览器想完全放弃字体展示,将这个问题掌握在自己手中。手机上的 Firefox 就绘制一个灰色矩形。
(如果您好奇的话,您的设备显示的是:。)
还有一个技巧。在「字体回退」 表的最后,macOS 添加了一个秘密字体,它有一个漂亮的名字:.LastResort。这种字体的目的非常简单,优雅地回退。它的任务是为每个丢失的字符提供一个始终美观的带问号的正方形。无论您想要什么字体,它将忽略字体设计师的.notdef 的绘制。
确保方块看起来一致是苹果的一贯做法。如果您对控制「字体回退」感兴趣,至少有一种简单的方法:您始终可以将包罗万象的字体放在「字体回退」表的最末端。这样的字体被称为后备字体:如 Adobe NotDef(绘制一致的方块),Adobe Blank(根本不绘制任何东西),以及 Last Resort 的早期版本,它实通过不同的形状至少向您显示这个文字自的 Unicode 区块。
.LastResort 那时它不是为了表现得完美,而仅仅为了避免灾难:
� 替换字符的入侵
�它与「字体回退」无关,但为了完整起见,我们需要讨论它。
它有一个无聊的名字:替换字符(Replacement Character,),并在出现严重错误时介入。
替换字符最常用于告诉您数据有问题,数字本身没有意义。如果数字没有意义,就没有理由保留它们,因此 � 字符与.notdef 不同。.notdef 它有自己的 Unicode 代码:您就可以随意复制和粘贴它,直到可以找到展示它的字体。而 � 则永远不会展示出其他含义的文字。
有趣的是,� 本身遵循正常的「字体回退」规则,一些字体设计者也包含了它。这也意味着 � 在不同的情况下看起来可能略有不同,尽管这里看不到.notdef 释放的疯狂创造力:
各种字体的替换字符,使用相同的字体大小复制
Emoji 的零零碎碎
你已经了解了「字体回退」、.notdef 的多个版本、苹果精心设计的问号 .LastResort 、以及另一个完全意味着其他东西的问号�。
但 Emoji 的到来让排版变得更加复杂。
从某种意义上说,表情符号非常简单。没有不同的文字,没有不同的语言,没有粗体或斜体。计算机上的所有表情符号通常都由一种大字体(软件)提供。
但表情符号至少在两个方面是独一无二的:
第一个它们经常改变。每年似乎都会推出大约 100 个新 Emoji,并对现有 Emoji 进行不少更新。文字这种以千年为时间单位的演变,在表情符号上正在以前所未有的速度改变。
与其他字形一样,表情符号遵循「字体回退」规则。操作系统或浏览器秘密地将表情符号字体添加到「字体回退」表中。
font-family: NotoEmoji, AppleColorEmoji, JoyPixels;
**,时长00:06
假设优先考虑较旧的表情符号文件(Noto Sans Emoji),表情符号覆盖范围较小,会导致回退到较新表情符号集的奇怪现象(Joy Pixels)
表情符号字体大小甚至比 Arial Unicode 和 Code 2000 更大,并且使用的新字体格式。(Mac 中的 Emoji 字体超过 200Mb,相当于几千个西方字体的体量。)
操作系统上的表情符号字体通常是最新的,因此回退到较旧的字体没有太大意义。但有时表情符号的发展速度就连操作系统也落后了。比如,iPhone 可以给 Mac 发一条包括忍者 (🥷)、皮卡车 (🛻) 和苍蝇 (🪰) 的短信。但 Mac 还无法渲染这三个 13.0 表情符号。
如果表情符号字体无法展示新的表情符号,通常意味着其他字体也无法处理它,这意味着这些表情符号将呈现为方块。
另一个奇怪的点是:越来越多的表情符号是复合的,将单独的 Emoji 用「零宽度连接符」这种不可见字符粘合在一起的形式出现。
新的黑猫表情符号实际上是「猫」 粘上 「黑色大方块」。
北极熊是一只「熊』粘上「雪花」表情符号。
穿燕尾服的女人是「穿着燕尾服的人」粘上「女性性别符」。
两个男人手牵着手,一个黑人,一个白人?它的底层有五个符号:「一个男人」、「深色肤色」「握手」「一个男人」和「浅色肤色」
在一台最新设备上这些表情符号将看起来很完美。但对于其他人呢?您可能会看到复合表情符号的某个部分,另外一部分则是豆腐:
🥷、🤵♀️、🐈⬛、🐻❄️、👩🏾🦳、👨🏿🤝👨🏻、👶🏻 一直在不同计算机上呈现
坎坷之路,以达星辰
「字体回退」在数字排版世界中为我们遇到的各种情况下提供帮助,尽管它有一些奇怪的副作:方向、拆解的 Emoji、奇怪的 Twitter 字体、笨拙的行高变动、意想不到的问号。我希望这边文章可以帮你一一解开这些谜团。
与「字体回退」一样,您可以在设备上检查的这些文字。但当你发送它时,剩下的只能交给命运。因此,当我写这篇文章时,我不知道 🥷 到达您的设备它们是否会呈现方块,或者 3 种不同的问号,又或者根本不显示。
您可能会遇到三个问号:.LastResort、旧金山的替换字符以及来自一种特定字体的 .notdef。希望您现在知道哪个是哪个以及为什么会看到它。
事实上,有时人们可能仍会看到方块、问号或悬挂的肤色 Emoji?这可能是「字体回退」下一个小小的代价。