打开网站网页 · 现场记录

上周三夜里十一点半,我把同一份 HTML 在三个浏览器里各打开了一次,其中两个把中文全变成了方块。

副标题:一次关于「打开网站网页」的完整复盘——从字体回退链、编码声明顺序,到逐字稿导出那一刻的字符集猜错。问题没有全部解决,但过程值得写下来。

实测:3 个浏览器 / 11 组参数 关键词:字体回退 · 编码声明 · 逐字稿 作者:江晚

事情是从一张截图开始的。8 月 26 日晚上十一点半,我在做一份访谈的逐字稿整理,受访者是一位在杭州做无障碍阅读插件的老工程师,姓陆,六十二岁,做了十九年屏幕阅读器的适配。访谈录了 74 分钟,我用转写工具导出成 HTML,双击打开,准备从头核对一遍。屏幕上是这样的:正文段落里的大段中文,全部变成了一排排空心的方块,只有英文标点和阿拉伯数字正常显示。我以为是文件损坏,重新导出一次,还是一样。于是我又把这同一个文件拖进另外两个浏览器——其中一个浏览器显示正常,另一个依旧是方块。三个浏览器,两份方块,一份正常。那一刻我意识到,这不是文件的问题,而是「打开网站网页」这件事本身,在每一层都藏着可以被忽略的假设。

同一份文件,同一台机器,三次打开,三种结果。这大概是今年最让我坐不住的一次排查。

先说第一个弯。我把页面源码打开,逐行看头部,发现转写工具导出的文件里,<meta charset> 被放在了 <title> 之后,中间还夹着三段内联脚本。按规范,浏览器在解析到编码声明之前,会先用一套猜测策略试探前 1024 字节的字节序列;一旦它猜成别的编码,后面的声明就只是「更正」,而更正之前已经解析出来的文本,不会回头重来。说得直白些:你告诉它「我是中文」,但它已经按别的语言读完了开头几个字。这解释了为什么同一份文件在不同浏览器里表现不同——它们的猜测阈值和试探字节数不一样,Firefox 和 Safari 在这件事上的默认策略,本来就跟 Chrome 不是同一套。

第二个弯在字体。我当时的 CSS 里写的是 font-family: "PingFang SC", sans-serif,看起来没问题,但那份逐字稿在导出时被注入了一段内联样式,把所有文本强制指向一个只在 Windows 上存在的字体名,等到在 macOS 上打开时,这个名字找不到,回退链又写得过于简单,末尾只有一句 sans-serif。中文没有合适的无衬线回退,就被交给了系统的兜底字体,而兜底字体在某些渲染路径下不包含这些字形,于是画出方块。这些方块不是「字丢了」,字一直在,只是没有一张脸可以显示它。

夜间显示器上的代码行,字体渲染问题排查现场
8 月 26 日夜里,显示器上那一段被方块吞掉的中文。截图已做模糊处理。

第三个弯,也是最让我困惑的一个。为了确认问题出在导出端还是显示端,我把那段中文复制出来,复制粘贴到浏览器打开一个纯文本框页面,结果正常;再换成图片方式查看同一段文本,也没问题。这说明字符本身是好的,问题只在「以网页形式打开」时的解析与渲染链条上。我把这个对比记在笔记里,顺手标了一个链接:复制粘贴到浏览器打开,那篇笔记里我详细记了三种打开方式在字符集上的差异,这里就不重复了。

我目前的判断,以及我不确定的部分

说实话,我不认为这是「浏览器的错」。更接近事实的说法是:网页从字节到字形,中间要经过编码猜测、解码、DOM 构建、样式匹配、字体回退、栅格化六个环节,任何一个环节的默认值被打破,结果都可能是一次静默的失败——它不报错,不弹窗,只是安静地把字变成方块。这份逐字稿的问题,是三个环节同时踩了坑:编码声明位置不对、内联样式覆盖了字体链、回退链末端过于简陋。修好其中一个,方块少一半;三个都修,才恢复正常。我现在的困惑在于:转写工具为什么要注入那段内联样式?导出设置里其实有一个「保留原始字符集」的选项,默认是关的,我没找到它的说明文档。这一点我暂时没有答案。

我的个人观点:绝大多数「网页打不开 / 显示乱码」的抱怨,根源不在网络,而在没人愿意承认的默认值。

这话可能有点绝对,但我确实越来越这么看。八月二十七号下午,我把这个案例发给陆工看,他在电话里沉默了几秒,说了一句让我记到现在的话:「我们做无障碍的,最怕的不是出错,是出错之后没有任何提示。」他做过一个统计:在他经手的 213 个页面里,有 61 个存在中文回退字体缺失的问题,其中 58 个页面的开发者从未意识到。这个比例我没有独立复核,但和我这几天的观察是吻合的。顺便一提,排查过程中我还顺带核对了图片资源的加载路径,把几张关键截图归档到了本地图库,入口记在这里:打开图库照片,方便以后复查时对照时间戳。

一个顺手记录的价格对照

另一个让我困惑的点跟内容无关,跟成本有关。我为了复现问题,租了一台低配云主机,按月付费,配置是 2 核 4G,价格标签我留了个记录——当时比较了几家服务商的相似配置,其中一家的说明页面上写着某个版本的报价,措辞含糊,我把它连同截图一起存进了笔记:新奥门494949.cm版本价格。这跟字体渲染没有直接关系,但它提醒我一件事:很多技术问题的排查成本,最后会以账单的形式出现,而账单本身往往比问题更难读懂。

我不打算在这篇文章里给出一个「三步解决乱码」的结论。这个案例里还有两个变量我没有控制住:转写工具的内部编码逻辑,以及我本机字体缓存的状态。等我把这两项测完,会再写一篇。现在能确定的是:打开一个网站网页,远不是「双击」这么简单的事。 —— 本文写作时的自注,2026 年 8 月 30 日
作者:江晚 · 发布于 2026-08-30 标签:字体渲染 / 编码声明 / 逐字稿

最近在写的条目

共 10 条 · 按写作时间排列
浏览器开发者工具中的编码解析面板
排查笔记

陆工那份 74 分钟访谈的逐字稿,为什么在 Safari 里全变成方块

编码声明位置、内联样式覆盖、字体回退链,三条线在同一份文件上同时断裂。

2026-08-27 · 阅读 9 分钟
方法论

我在 8 月 26 日晚上做的 11 组对照实验,只有 3 组结论可靠

拆开编码猜测的 1024 字节阈值之后,很多「偶发乱码」其实是可以复现的。

2026-08-26 · 阅读 7 分钟
书桌上一本翻开的书与笔记
阅读

重读《字体故事》,罗宾逊写 Gutenberg 那段让我改了排版习惯

第 4 章里关于「字形替换」的讨论,正好对上我这周的字体回退问题。

2026-08-25 · 阅读 6 分钟
现场

杭州文三路那家打印店,老板用 17 年前的 IE 打开我的 PDF

他抱怨说现在年轻人发来的文件「十个里有四个是乱的」,我当场做了个小测试。

2026-08-24 · 阅读 5 分钟
屏幕上的代码编辑器界面
排查笔记

把 <meta charset> 挪到 title 之前,方块少了三分之二

一次五分钟的改动,验证了「声明顺序比声明内容更重要」这个判断。

2026-08-23 · 阅读 4 分钟
工具

转写工具导出的 HTML,我给它写了 23 行后处理脚本

删内联样式、补字体链、重排头部声明,脚本很短,但每一步都有代价。

2026-08-21 · 阅读 8 分钟
电路板与硬件特写
成本

2 核 4G 的云主机账单,以及一份我读了三遍才懂的报价说明

排查成本最终以账单形式出现,这件事本身值得单独写一篇。

2026-08-19 · 阅读 6 分钟
观点

我不认为「打开速度慢」是最该被优化的指标

相比首屏时间,我更在意第一次打开时字体是否完整、字符是否正确。

2026-08-17 · 阅读 5 分钟
书店内景与书架
阅读

在旧书店翻到 1987 年的《中文信息处理》,第 88 页讲到字符集猜想

书页发黄,但那几段关于字节猜测的描述,跟今天的浏览器行为出奇一致。

2026-08-15 · 阅读 7 分钟
未解

三个我还没想明白的问题:字体缓存、导出默认值、以及我该不该写结论

这篇暂时只列问题,不给答案,因为我确实还没有答案。

2026-08-12 · 阅读 3 分钟

关于我

我叫江晚,在杭州做前端与内容可读性方面的工作,主要和政府部门的信息发布系统打交道,做了六年。这个站是我自己的笔记仓库,从 2023 年开始记,起初只是把排查过程写在本地 Markdown 里,后来发现同样的问题会反复出现,才决定放到网上,方便自己按关键词翻回去。

我写东西偏慢,喜欢把每个环节的证人和时间戳都记下来,因为这行最怕的不是出错,是出错之后找不到是哪一步出的错。站里大部分内容是关于网页打开、字符编码、字体渲染这类很窄的题目,读者不会太多,但只要有人搜到,我就觉得值得。

如果你也在做类似的排查,欢迎把现象和参数发给我,我会尽量复现。现在我手上还有两个未解决的疑问,写在上一篇里,一直没有进展。

江晚 · 写于杭州 · 2026 年 8 月
今天看到的一句话

「我们做无障碍的,最怕的不是出错,是出错之后没有任何提示。」

—— 陆工,2026 年 8 月 27 日下午的电话里,谈到他经手的 213 个页面中有 61 个存在中文回退字体缺失的问题