必须位于内第一个有效标签位置(BOM除外),且仅写一次;浏览器仅扫描前1024字节识别,若被注释、置于后、或前面有BOM/空格/非法字符即失效。

meta charset 必须写在
开头且只写一次
浏览器只扫描 HTML 前 1024 字节来识别编码, 如果被注释、放在 后、或前面有 BOM / 空格 / 之外的字符,就可能失效。常见错误包括:(缺短横)、(大小写不敏感但非标准写法)、(HTML5 不推荐,仅兼容旧场景)。
正确写法只有一种:,且必须是 内第一个有效标签(BOM 除外),位置示例:
<meta charset="utf-8"><title>我的页面</title> ...
文件保存编码必须是 UTF-8(不含 BOM)
VS Code 默认在 Windows 上保存为 UTF-8 with BOM,而 BOM(ef bb bf)会卡在 前面,导致浏览器跳过该标签。Notepad++ 里选「转为 UTF-8」而非「UTF-8-BOM」;VS Code 保存时点右下角编码 → 「Save with Encoding」→ 选 UTF-8(明确不含 BOM)。
验证方式:
- Linux/macOS:
head -c 4 yourfile.html | xxd,输出不含ef bb bf - Windows PowerShell:
Get-Content yourfile.html -Encoding Byte | Select -First 3,前三字节不能是239, 187, 191
HTTP 响应头 Content-Type 优先级高于 meta
即使 写对了,如果服务器返回的响应头是 Content-Type: text/html; charset=gbk 或压根没带 charset,浏览器仍会按响应头解析——此时页面照样乱码。
检查方法:F12 → Network → 刷新 → 点 HTML 请求 → 查看 Response Headers 中的 Content-Type 字段。
修复方式取决于服务器:
- Apache:
.htaccess加AddDefaultCharset UTF-8 - Nginx:
server或location块加charset utf-8; - Node.js(Express):
res.set('Content-Type', 'text/html; charset=utf-8')
后端模板渲染时 meta 标签可能被覆盖或遗漏
用 EJS、Thymeleaf、Django 模板等动态生成 HTML 时, 很容易被写在子模板里、被母版覆盖、或因条件判断未渲染。尤其注意:母版中 已有 charset,子模板又插入一个,会导致两个同名标签。
排查建议:
- 直接查看浏览器最终加载的 HTML 源码(不是编辑器里的源文件),确认
是否真实存在且位置正确 - 检查模板继承逻辑,确保 charset 只在最外层
中声明一次 - 若使用构建工具(如 Vite、Webpack),确认 HTML 插件未自动注入错误的 meta 标签
实际乱码往往不是单点问题,而是文件编码、meta 标签、HTTP 响应头、模板逻辑四者之一或多个不一致。最容易被忽略的是:**本地编辑器显示正常,但上传到服务器后因 FTP 模式(ASCII vs Binary)或 Git 自动换行(core.autocrlf)悄悄改变了文件编码或引入不可见字符**。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











