起因很简单:在 Safari 里打开本站,字体看起来和 Chrome/Windows 不太一样。折腾一番后发现,根源是字体栈里的字体在不同系统上回退到了不同字体。干脆上了「自托管字体子集」方案——字体文件放自己服务器,所有浏览器渲染完全一致。记录一下全过程和踩的坑。
一、问题:同一个网站,不同系统字体不一样
主站正文用的字体栈是 "SimSun"(宋体), "Songti SC", ...——SimSun 是 Windows 专属字体,Mac/iOS 没有,于是 Safari 自动回退到「Songti SC(华文宋体)」,字形和粗细都不一样;加上 Safari 对中文的渲染更细,差别肉眼可见。
博客的问题更隐蔽:正文用的是仿宋栈(FangSong → 仿宋 → STFangsong → ...),但 Mac 和 Windows 上的仿宋根本不是同一个字体,回退结果自然不同。
二、方案:自托管字体子集(全平台像素级一致)
治本的办法是把字体文件放到自己服务器上,让所有浏览器加载同一个文件:
- 下载开源字体:思源宋体 Noto Serif SC(Google/Adobe 出品)+ 朱雀仿宋(TrionesType 开源仿宋,博客正文专用)
- 用 fonttools
pyftsubset按网站实际用到的字切子集,转 woff2:- 主站:只收录本站页面的 1037 个字 → 251K
- 博客:文章内容 + 主站字符 ≈ 1077 字 → 思源宋体 256K + 朱雀仿宋 340K
- CSS
@font-face引用,字体栈把 webfont 放第一位
效果:任何浏览器、任何系统(含 Safari),看到的都是同一个字体文件。
三、中途的一次实验:微软雅黑
中间试过把全部字体换成「微软雅黑 + 不加粗」——结果发现一个事实:微软雅黑是 Windows 专属字体,Mac 上会自动回退成苹方(PingFang),永远无法真正统一。最终回到宋体路线:标题思源宋体、正文朱雀仿宋,保持网站「深墨底 + 衬线」的设计气质。
四、附带的优化
- preload 预加载:主站 7 个页面 + 博客模板 header,消除字体闪烁(FOUT)
- 字体缓存 1 年:nginx
expires 1y + immutable,二次访问零下载 - 删掉 Bold 字重:统一不加粗,只留 Regular 一个文件
font-synthesis: none:禁止 Safari 在字体缺字重时合成假粗体(之前「看着像加粗」的元凶之一)- 字号体系重排:正文标题终于有了层级(h1 24px → h5 17px),正文/评论行高放到 1.8,评论内容 13.5px → 15px,首页文章标题 32px → 22px
五、踩坑记录:标题为什么会变黑
调整字号时用正则批量改 CSS,结果把 .loglist-title(文章标题)和 .loglist-tag(标签)两条规则误合并了——标题继承了标签规则的 color: #000000,整个首页标题变黑。排查半天才发现是 CSS 规则结构被破坏。
教训:改 CSS 用正则要格外小心,改完必须做两件事——① git diff 逐行检查只改了目标属性;② 校验花括号配对(553/553)。这次就是靠 diff 发现规则被吞并的。
六、最终效果
- 全平台字体一致(Safari/Chrome/Windows/手机)
- 正文仿宋书卷气、标题宋体呼应主站、行距舒适
- 字体总量:主站 251K、博客 ~600K,配合缓存几乎无感
如果你也遇到「同一网站不同设备字体不一样」的问题,自托管字体子集是目前最可靠的解法——比调字体栈顺序彻底得多。
—— 2026.08.16 于 島上隨筆