<meta charset="UTF-8">必须紧贴<head>开头且为首个非空白非注释子元素,否则浏览器仅扫描前1024字节找不到它,将回退至系统默认编码(如Windows的GBK)导致中文乱码。

meta 元素的 charset 属性本身不防乱码,它只是告诉浏览器“请用这个编码去解码后续字节流”——前提是位置对、文件真、响应头不打架。
为什么 meta charset="UTF-8" 放错位置就失效
浏览器解析 HTML 时,只扫描前 1024 字节(部分引擎是 512 字节)找 meta charset;一旦错过,立刻 fallback 到系统默认编码(Windows 是 GBK,Linux/macOS 常是 ISO-8859-1),中文直接变 或乱码。
-
meta charset必须紧贴<head>开始,且是<head>内第一个非空白、非注释的子元素 - 前面不能有 BOM(
ef bb bf)、空格、换行、HTML 注释<!-- -->、<title>或<script> - 错误写法示例:
<head><title>首页</title><meta charset="UTF-8"></head>——<title>挡住了,大概率失效
文件实际编码和 meta charset 不一致会怎样
哪怕 meta 写得再标准,如果 HTML 文件本身不是 UTF-8(无 BOM)保存的,浏览器仍会用 UTF-8 去硬解一串 GBK 字节,结果就是中文全乱,且往往无法通过刷新恢复。
- VS Code 右下角显示 “GBK” 或 “UTF-8 with BOM”?必须点它 → “Save with Encoding” → 选
UTF-8(明确排除with BOM) - Notepad++:菜单栏“编码” → “转为 UTF-8 编码”(不是 “UTF-8-BOM”)
- 命令行验证:
head -c 4 index.html | xxd,输出含ef bb bf就说明还有 BOM,得清掉
HTTP 响应头里的 Content-Type 为什么能覆盖 meta charset
当页面通过 http:// 或 https:// 加载时,服务器返回的 HTTP 响应头中 Content-Type: text/html; charset=gbk 的优先级高于 HTML 内任何 meta 声明。浏览器直接按 gbk 解码,meta charset="UTF-8" 形同虚设。
立即学习“前端免费学习笔记(深入)”;
- Chrome DevTools → Network → 刷新 → 找主 HTML 请求 → Headers → Response Headers → 看
Content-Type - Nginx 配置要加:
charset utf-8;(注意小写utf-8,不是UTF-8) - Express.js 中要在
res.send()前调用:res.set('Content-Type', 'text/html; charset=utf-8') - 本地双击打开
file://页面时,HTTP 头不存在,此时meta charset是唯一依据,更得严守位置和编码一致性
真正卡住乱码的从来不是某个标签怎么写,而是三者是否咬死:文件磁盘字节流是 UTF-8(无 BOM)、meta charset="UTF-8" 在 <head> 最开头、HTTP 响应头明确声明 charset=utf-8。漏掉任一环,中文就可能在某个环节被错误解码一次,之后再也救不回来。



















