必须置于最开头且文件为utf-8编码,因浏览器仅扫描前1024字节找首个charset声明;若含中文等非ascii字符或存在注释/bom/空格在前,即触发系统默认编码(windows gbk/macos linux iso-8859-1)导致乱码,后续meta无效。

meta charset 必须放在 最开头,且文件本身得是 UTF-8 编码 —— 少一个环节,中文、emoji、用户输入内容就可能直接变问号或方块。
为什么 meta charset="UTF-8" 放在 <title></title> 后面会失效
浏览器解析 HTML 时,只扫描前 1024 字节找第一个 meta charset;一旦遇到非 ASCII 字符(比如中文 <title>你好</title>),就会立刻 fallback 到系统默认编码(Windows 是 GBK,macOS/Linux 是 ISO-8859-1),后面再写 meta 也救不回来。
-
<title>你好</title> <meta charset="UTF-8">→ 中文标题已按 GBK 解析,乱码已发生 -
<meta charset="UTF-8"> <title>你好</title>→ 正确,解析器从第 1 字节起就用 UTF-8 - 注释、BOM、空格、换行都算“非 ASCII 前导内容”,
<!-- 注释 --><meta charset="UTF-8">同样失效
VS Code / Notepad++ / Sublime 怎么确保保存为 UTF-8(带 BOM)
编辑器选“UTF-8”不等于文件就是 UTF-8 —— 很多工具默认“UTF-8 without BOM”,而 IE、部分本地双击打开的场景(file:// 协议)会因缺 BOM 直接 fallback 到 GBK。
- VS Code:右下角点击编码 → Save with Encoding → 选
UTF-8 with BOM(不是默认的UTF-8) - Notepad++:菜单栏 编码 → 转为 UTF-8-BOM → 再 另存为
- Sublime Text:File → Save with Encoding →
UTF-8 with BOM(部分版本需插件支持) - 验证方式:用十六进制编辑器看文件头是否为
EF BB BF;或终端执行head -c 3 index.html | xxd
HTTP 响应头 Content-Type 比 meta 更优先,但常被忽略
只要走 HTTP(Nginx/Apache/Express),浏览器就以响应头里的 Content-Type: text/html; charset=utf-8 为准;meta 只是 fallback。线上乱码,90% 是这里没对齐。
- Nginx:在
server或location块加charset utf-8; - Apache:.htaccess 里写
AddDefaultCharset UTF-8,或用Header set Content-Type "text/html; charset=UTF-8" - Express:在
res.send()前调用res.set('Content-Type', 'text/html; charset=utf-8') - 查错方法:F12 → Network → 点开 HTML 请求 → Response Headers → 看
Content-Type值是否含charset=utf-8
生成模板时最容易漏掉的三个点
手写或脚手架生成的 HTML 模板,常因“看起来能显示”就跳过验证,结果上线后部分环境崩溃。
-
DOCTYPE前不能有任何字符 —— BOM 若放在之前,某些旧版 IE 会触发怪异模式,连 <code>meta charset都不读 -
charset的值必须是"UTF-8"(全大写 U/T/F,带短横,数字 8);"utf8"、"utf-8"、"UTF8"在 Safari、Edge 或 WebView 中可能被忽略 - 动态模板(如 EJS、Pug)里拼接中文或变量时,要确认模板引擎输出时没二次转码 —— 例如 Express 默认
res.render()不设 charset,得手动配app.set('view engine', 'ejs'); app.engine('html', require('ejs').renderFile);并确保Content-Type已统一
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











