<meta charset="UTF-8">必须置于<head>最开头、任何非ASCII字符(含BOM、注释、换行、<title>)之前,否则浏览器仅扫描前1024字节且只识别ASCII范围内的<meta>,一旦被BOM、注释或<title>干扰,即fallback至GBK或ISO-8859-1,导致中文乱码、emoji显示为方块、JS报错。

meta charset="UTF-8" 必须放在 <head> 开头、任何非 ASCII 字符(包括 BOM、注释、换行、<title>)之前,否则浏览器可能 fallback 到 GBK 或 ISO-8859-1,直接导致中文乱码、emoji 显示为方块、JS 报 Invalid or unexpected token。
为什么 meta charset 放错位置就失效
浏览器解析 HTML 时只扫描前 1024 字节,且仅识别 ASCII 范围内的字符来提取 meta charset。一旦开头存在:
- BOM(
EF BB BF)——哪怕只是文件保存时多加的三个字节,也会让整个meta标签被跳过 - 注释
<!-- -->—— 注释符号本身是 ASCII,但注释内容若含中文或 emoji,就超出扫描范围 - 换行或空格后跟
<title>——<title>标签不是 ASCII-only,会中断 charset 识别流程
此时浏览器放弃解析,退回到系统默认编码:Windows 下是 GBK,macOS/Linux 下常为 ISO-8859-1,结果就是页面文字全变“”或“???”。
HTML 文件保存时必须选 “UTF-8 without BOM”
VS Code、Sublime Text、Notepad++ 默认保存行为不一致:
立即学习“前端免费学习笔记(深入)”;
使用 PptxGenJS 和 Python 解析,将结构化的 HTML/CSS 幻灯片内容转换为原生、可编辑的 PowerPoint(.pptx)演示文稿。
- VS Code 新建文件默认是
UTF-8,但“另存为”时若误选UTF-8 with BOM,就会在文件头写入EF BB BF - Notepad++ 默认是
UTF-8 with BOM,必须手动点“转为 UTF-8”(不含 BOM) - Sublime Text 的
Save with Encoding → UTF-8是安全的,它默认不含 BOM
验证方式:用命令行执行 file -i index.html(macOS/Linux)或 PowerShell 执行 Get-Content index.html -Encoding Byte | Select -First 3,确认输出不含 239, 187, 191。
CSS 文件编码必须和 HTML 保持一致
外部 CSS 文件(如 style.css)若用 GBK 保存,而 HTML 声明了 UTF-8,浏览器仍会按 HTML 的 charset 解析 CSS 内容,导致:
- CSS 中的中文注释或字体名(如
font-family: "PingFang SC", "Microsoft YaHei")解析失败 - @font-face src 中含中文路径时,路径被截断或乱码
- 某些构建工具(如 html-webpack-plugin)在注入 CSS 时抛出编码异常
实操建议:
- 所有 CSS 文件也统一用
UTF-8 without BOM保存 - 避免在 CSS 中写中文内容;必须写时,用 Unicode 转义(如
\4F60\597D)更稳妥 - 用
<link rel="stylesheet" href="style.css">引入,不要用@import—— 后者不继承 HTML 的 charset,且加载更慢
HTTP 响应头比 meta 更优先,但本地开发常被忽略
当通过 http:// 或 https:// 访问页面时,服务器返回的 Content-Type: text/html; charset=UTF-8 会覆盖 meta charset;但本地双击打开 file:// 时,HTTP 头不存在,完全依赖 meta 和文件编码。
- Nginx 配置需加
charset utf-8;(在http、server或location块中) - Apache 需在
.htaccess或配置中写AddDefaultCharset UTF-8(注意不是UTF8) - Node.js/Express 中,
res.set('Content-Type', 'text/html; charset=UTF-8')要早于res.send() - Python 自带服务器(
python -m http.server)不发 charset,默认 fallback 到 ISO-8859-1,务必改用其他本地服务
真正容易被绕过的点是:你以为改了 meta 就万事大吉,但没验证服务器响应头是否生效,也没确认 CSS 文件自己是不是悄悄用了 GBK 编码 —— 这两个漏掉一个,乱码就还在。


















