<meta charset="UTF-8">必须置于<head>开头,因浏览器解析HTML时遇非ASCII字符会立即回溯查找最近charset声明;若其位于<title>后或动态插入,前置内容已被错误解码,导致首段乱码且不可刷新修复。

HTML文档编码必须设为 UTF-8,且要三重保障:文件保存格式、<meta charset="UTF-8"> 声明、HTTP 响应头 Content-Type 一致;只做其中一项,乱码风险极高。
为什么 <meta charset="UTF-8"> 必须放在 <head> 开头?
浏览器解析 HTML 时,一旦遇到非 ASCII 字符(比如中文、emoji),会立刻回溯查找最近的 <meta charset>。如果它出现在 <title> 后面或被 JS 动态插入,前面已读入的字节可能已被错误解码,导致标题或首段文字乱码——这种错无法靠刷新修复。
- 必须紧贴
<head>开始,建议在<title>之前 - 不能写成
<meta http-equiv="content-type" content="text/html; charset=UTF-8">(HTML5 已弃用,兼容性差) - 不能加斜杠闭合,即
<meta charset="UTF-8"/>是无效写法,部分旧解析器会忽略 - 大小写敏感:
utf-8可接受,但UTF8或utf8在极少数老旧环境可能失效
HTTP 响应头 Content-Type 比 <meta> 更优先
当服务器返回 HTML 时,如果响应头里带了 Content-Type: text/html; charset=GBK,哪怕页面里写了 <meta charset="UTF-8">,浏览器也以响应头为准——这是 W3C 规范强制要求。常见于 Nginx/Apache 配置遗漏或反向代理层覆盖。
- Apache:在
.htaccess或虚拟主机配置中加AddDefaultCharset UTF-8,或用Header set Content-Type "text/html; charset=UTF-8" - Nginx:在
server或location块中加charset utf-8;(注意是小写utf-8,不是UTF-8) - Node.js(Express):路由中调用
res.set('Content-Type', 'text/html; charset=utf-8'),不能只设res.charset = 'utf-8' - 验证方式:Chrome DevTools → Network → 点开 HTML 请求 → Headers → Response Headers → 查
content-type字段
编辑器保存编码 ≠ 页面实际编码
VS Code 显示“UTF-8”,不代表文件真正以 UTF-8 无 BOM 形式保存。尤其从旧系统复制粘贴内容后,可能混入隐藏的 BOM(Byte Order Mark)或残留 GBK 字节,导致 <meta> 和响应头都正确,但页面仍局部乱码。
立即学习“前端免费学习笔记(深入)”;
- VS Code:右下角编码显示点击 → “Save with Encoding” → 选
UTF-8(不是UTF-8 with BOM) - Notepad++:编码 → 转为 UTF-8(无 BOM)→ 再保存
- Sublime Text:File → Save with Encoding → UTF-8
- 命令行验证:
file -i yourfile.html(Linux/macOS)或用xxd yourfile.html | head查前几个字节是否含ef bb bf(BOM)
最容易被忽略的是:本地双击打开 HTML 文件(file:// 协议)时,浏览器完全不读 HTTP 响应头,只依赖 <meta> 和文件自身编码。此时若编辑器保存错了,或漏写 <meta>,乱码必然发生,且无法通过服务端配置修复——务必养成「本地预览也走本地服务器」的习惯,比如用 VS Code 的 Live Server 插件。



















