<meta charset="UTF-8">必须置于<head>最开头、前1024字节内且文件为UTF-8无BOM编码,否则浏览器fallback至系统默认编码(如Windows的GBK)导致乱码;HTTP响应头charset优先级高于meta,但file://协议下仅依赖meta。

meta charset="UTF-8" 必须出现在 <head> 开头的前 1024 字节内,且文件本身必须是 UTF-8 编码(无 BOM),否则中文会变成 或乱码符号。仅写这行标签但忽略文件实际编码,90% 的乱码问题依然存在。
为什么 meta charset="UTF-8" 放在 <title> 后面就失效
浏览器解析 HTML 时,只扫描前 1024 字节寻找 meta charset;一旦错过,就会 fallback 到系统默认编码(Windows 是 GBK,Linux/macOS 是 ISO-8859-1)。此时哪怕后面写了 <title>你好</title>,浏览器也早已用 GBK 解析过那串字节,把 UTF-8 的中文二进制当 GBK 读,结果就是乱码或 JS 报 Uncaught SyntaxError: Invalid or unexpected token。
-
<head><title>你好</title><meta charset="UTF-8"></head>→ 失效 -
<head><meta charset="UTF-8"><title>你好</title></head>→ 有效 - 注释、空格、BOM(
EF BB BF)都算进前 1024 字节,会挤占有效位置
如何验证 HTML 文件真实编码是否为 UTF-8(无 BOM)
不能只看编辑器右下角显示 “UTF-8” —— VS Code 默认保存为 “UTF-8 with BOM”,Notepad++ 默认转为 “UTF-8-BOM”,这些都会导致 IE、某些 WebView 或 Node.js 静态服务出问题。
- Linux/macOS:运行
file -i your.html,输出含charset=utf-8才对;若显示charset=gbk或us-ascii,说明文件没转成功 - 检查 BOM:运行
xxd -l 4 your.html,开头不是ef bb bf才安全 - VS Code:打开文件 → 右下角点击编码名 → 选 “Reopen with Encoding” 确认当前内容按什么解码;再点 “Save with Encoding” → 严格选 “UTF-8”(不带 “with BOM”)
HTTP 响应头 Content-Type 和 meta charset 谁优先
HTTP 响应头中的 Content-Type: text/html; charset=... 优先级高于 meta charset。如果服务器返回 charset=GBK,即使 HTML 里写了 UTF-8,Chrome/Firefox 也会强制按 GBK 解析。
立即学习“前端免费学习笔记(深入)”;
- Nginx:在
http、server或location块中加charset utf-8;(注意小写,不能写charset=UTF-8) - Apache:
.htaccess中写AddDefaultCharset UTF-8 - Express.js:在
res.send()或res.render()前调用res.set('Content-Type', 'text/html; charset=utf-8') - 本地双击打开(
file://协议):响应头不存在,完全依赖meta charset,此时位置和文件编码更关键
lang="zh-CN" 和 charset 是两回事,别混用
lang 属性只影响屏幕阅读器、搜索引擎语义识别、部分 CSS 伪类(如 :lang(zh)),**完全不影响字符解码过程**。设了 lang="zh-CN" 但没处理好 UTF-8 编码,该乱码还是乱码。
- 正确写法:
<html lang="zh-CN">(放在根元素),配合<meta charset="UTF-8"> - 错误认知:“加了 lang 就能显示中文” → 完全无关
- 多语言页面中,
<p lang="en">Hello</p>和<p lang="zh-CN">你好</p>仍需共用同一套 UTF-8 编码保障
最容易被跳过的其实是文件保存动作:改完 meta 标签后,必须手动执行“另存为 UTF-8(无 BOM)”,而不是直接 Ctrl+S —— 多数编辑器的默认保存行为并不会变更实际编码格式。



















