根本原因是iframe加载的页面未正确声明编码,必须同时满足:meta charset="UTF-8"在head最前、文件物理保存为UTF-8(无BOM)、服务器响应头含charset=utf-8;父页编码对iframe完全无效。

为什么 <iframe></iframe> 里中文显示为方块或问号
根本原因不是 iframe 本身有问题,而是它加载的 HTML 页面没正确声明编码。浏览器对 <iframe src="xxx.html"></iframe> 的内容,会独立解析其 HTTP 响应头 + <meta charset>,两者不一致或缺失任一,就容易 fallback 到 ISO-8859-1 或系统默认编码,中文直接崩。
<iframe></iframe> 加载的页面必须独立满足 UTF-8 三要素
被嵌入的 HTML 文件不能“搭便车”——它得自己搞定编码,和父页无关。缺一不可:
-
<meta charset="UTF-8">必须出现在最开头,前面不能有任何空白、注释或 BOM - 该 HTML 文件物理保存格式必须是 UTF-8(无 BOM 更稳妥);用 VS Code 打开后右下角确认显示 “UTF-8”,不是 “GBK” 或 “ISO-8859-1”
- 服务器返回该文件时,HTTP 响应头
Content-Type必须含charset=utf-8,例如text/html; charset=utf-8
三者中任意一个失效,iframe 就可能乱码。尤其注意:Nginx/Apache 默认不加 charset,Express res.sendFile() 也不带 charset,必须显式设置。
父页面加 charset 对 iframe 完全无效
很多人在父页 里写 <meta charset="UTF-8">,以为能“传染”给 iframe —— 这是错觉。iframe 是独立文档上下文,它的编码解析完全隔离。你甚至可以把父页设成 GBK,只要 iframe 源页三要素齐全,中文照样正常。
立即学习“前端免费学习笔记(深入)”;
验证方法很简单:
- 直接在浏览器地址栏输入 iframe 的 src URL 单独打开它
- 看是否乱码:如果单独打开就乱,问题 100% 出在那个页面自身
动态生成 iframe 内容时容易踩的坑
用 JS 拼 HTML 字符串再写入 iframe.contentDocument,最容易翻车:
- JS 字符串本身是 Unicode,但写入时若没指定 document 编码,某些老浏览器可能按系统 locale 解析
- 更稳妥做法:先用
iframe.contentDocument.open(),再write()时确保字符串含<meta charset="UTF-8">,且整个字符串以 UTF-8 字节流方式处理 - Node.js 后端拼 HTML 返回给 iframe src,必须用
res.set('Content-Type', 'text/html; charset=utf-8'),不能只靠<meta>
BOM 是隐形杀手:哪怕文件存为 UTF-8 with BOM,<meta charset> 前多了那 3 个字节,部分浏览器(尤其旧版 Safari)会直接忽略 meta 标签。务必用 file -i xxx.html 或 VS Code 查看真实编码。



















