什么是豆腐字 (Tofu)
本文约 4 分钟读完。
屏幕上突然出现 □ 这样的空白方块,这就是所谓的「豆腐字 (tofu)」- 字体不支持该字符时的显示方式。当屏幕上出现一排 □ 或 ⌷ 时,看起来像是某种 bug,但实际上这是渲染引擎在诚实地告诉你「我没有这个字符」。 这种现象在 emoji 和装饰文字中经常遇到,了解对策后可以让设计和 UI 决策更加合理。
定义
豆腐字 (tofu) 是指当字体没有某个 Unicode 码位对应的字形时, 作为替代而绘制的空白方块或占位图形。技术上来说,它是 Unicode 规范和 OpenType 规范中 「.notdef glyph」(not defined glyph,未定义字形) 的通俗叫法。
「豆腐」这个称呼源于其外观像白色方块的豆腐,在 Web 开发者和字体设计师之间广泛流传。 Google 为了覆盖全球所有文字而开发的字体家族取名为「Noto」(No Tofu = 消灭豆腐),正是源于这个词。
豆腐字出现的原因
1. 字体缺少该字符
最典型的原因。当网页 CSS 指定的字体没有某个 Unicode 码位对应的字形时, 浏览器会依次尝试后备字体,如果仍然找不到对应字形,就会显示豆腐字。
2. 系统字体版本过旧
较新的 emoji (如 Unicode 14.0 以后的 emoji) 不包含在旧版 OS 的系统字体中。 Android 8 及更早版本、iOS 12 及更早版本、Windows 10 (某些时期之前) 可能会将最新 emoji 显示为豆腐。
3. 未指定字体导致后备失败
如果 CSS 中 font-family 只指定了一个字体,没有写通用后备 (如 sans-serif), OS 可能无法推测出合适的字体,从而显示豆腐。
4. 装饰文字 (Unicode 扩展区域)
emoji 艺术中常用的 𓆩 𓆪 𖣘 ৎ 等装饰文字位于 Unicode 的辅助多语言平面或私用区 (PUA), 标准字体通常不包含这些区域。这是在旧设备上最容易变成豆腐的代表。
豆腐字的外观变体
| 显示 | 环境 | 含义 |
|---|---|---|
| □ | 大多数 OS | 标准 .notdef 字形 |
| ⌷ | 部分字体 | 未定义的替代显示 |
| ? | 旧设备 | 问号替代 |
| U+1F33B (十六进制) | 调试显示 | 以字符串形式显示码位 |
对策
1. 用 Web 字体确保字符覆盖
将 Google Fonts 的 Noto Color Emoji 或 Twemoji 作为 Web 字体分发,就可以不依赖用户设备的字体来显示 emoji。 这是品牌需要保持视觉一致性时的标准做法。
2. 优化字体栈
在 CSS 中依次指定多个字体,让不支持的字符由下一个字体来补充。
font-family: "Hiragino Sans", "Yu Gothic", "Noto Color Emoji", sans-serif;3. 选择兼容性高的字符
在 emoji 艺术中,使用装饰文字之前先考虑「能否用广泛支持的符号 (⌒ ⊹ ✧ ☆) 来替代」。 如果确实需要使用复杂的装饰文字,请事先在目标受众的设备上确认是否能正常显示。
4. 文本显示的替代方案
如果豆腐化的可能性很高,可以用 JavaScript 检测不支持的字符,并替换为图片或替代文本。 虽然实现成本较高,但在将 SNS 评论嵌入网页时很有效。
实际表现
- 旧版 Android: 装饰文字 𓆩 𖣘 容易变成豆腐
- 旧版 Windows: emoji 整体显示为黑白或豆腐
- 部分 Linux 发行版: 默认字体不支持 emoji,导致豆腐化
- 旧版 iOS: 最新 emoji (Unicode 15.0 以后) 可能变成豆腐
常见误解
- ❌「豆腐字是 bug」→ ✅ 这是正常的「不支持」信号
- ❌「换个字体就能解决」→ ✅ 新字体也必须包含该字形才行
- ❌「加载 Web 字体就能在所有设备上显示」→ ✅ 某些浏览器可能下载失败