必须在html的中首个标签声明,确保浏览器正确解析中文;服务端响应头content-type优先级更高,js文件也须存为utf-8无bom。

HTML 文件开头必须声明 charset,否则浏览器可能乱码
浏览器解析 HTML 时,默认编码不是 UTF-8,尤其在 Windows 系统下容易 fallback 到 GBK 或 ISO-8859-1,导致中文显示为方块或问号。最可靠的方式是在 中用 <meta charset="UTF-8"> 声明,且必须是 中**第一个** <meta> 标签(部分旧版 IE 要求它在前 1024 字节内)。
- 不要写成
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">—— 冗余且兼容性不如charset属性 - 服务端响应头里有
Content-Type: text/html; charset=utf-8时,它优先级高于 HTML 中的<meta>,但不能依赖——本地双击打开文件时响应头不存在,全靠<meta> - 如果用了
<meta charset>还乱码,检查编辑器保存时是否真用了 UTF-8 编码(不是 UTF-8 with BOM);VS Code 默认是 UTF-8,但 Sublime 或记事本容易存成带 BOM 的 UTF-8,BOM 会干扰某些 JS 解析
<script></script> 和 <link> 标签的 charset 属性早已废弃
早期 HTML4 允许给外部资源加 charset 属性,比如 <script src="a.js" charset="UTF-8"></script>,但 HTML5 已将其标记为 obsolete。现代浏览器完全忽略该属性,脚本/样式表的编码由其自身 HTTP 响应头或 BOM 决定。
- 删掉所有
<script charset="..."></script>和<link charset="...">—— 不仅无效,还可能误导维护者 - JS 文件本身必须保存为 UTF-8(无 BOM),若含中文字符串或注释,编码不对会导致语法错误或乱码,和 HTML 的
<meta charset>无关 - 遇到
Uncaught SyntaxError: Invalid or unexpected token且错在中文字符附近,大概率是 JS 文件编码错了,不是 HTML 没设对
服务器配置比 HTML 标签更底层、更可靠
当 HTML 通过 HTTP 传输时,服务器返回的 Content-Type 响应头中包含 charset 参数,它的优先级高于 HTML 内任何 <meta>。比如 Nginx 默认不带 charset,PHP 默认输出 text/html 不带编码,结果就是浏览器自猜。
- Nginx 配置中加
charset utf-8;(在http、server或location块里),它会自动给text/html、text/css、application/javascript等类型加上charset=utf-8 - Apache 用
AddDefaultCharset UTF-8,但注意它对text/plain也生效,可能影响 API 响应,建议用mod_headers精确设置 - Node.js 的
express:用res.set('Content-Type', 'text/html; charset=utf-8'),或全局中间件统一设置;不推荐只靠res.send(),因为它默认不带 charset
特殊场景:动态生成 HTML 或模板引擎里的编码陷阱
用 PHP、Python Jinja、JS 模板拼接 HTML 时,容易在字符串拼接阶段就引入编码问题。比如 PHP 中 echo "<meta charset="UTF-8">" 没问题,但如果 PHP 文件本身是 GBK 编码,而里面写了中文字符串,输出到 HTML 就会错位。
立即学习“前端免费学习笔记(深入)”;
- 确保模板文件(.php / .jinja / .ejs)保存为 UTF-8(无 BOM)
- PHP 中避免混用
mb_*函数和普通字符串函数处理中文,例如strlen()计算字节数而非字符数,可能导致截断出错 - Vue / React 等前端框架渲染的 HTML,其编码仍由宿主 HTML 文件决定;框架内部状态是 JS 字符串,不受 HTML
<meta>影响,但最终插入 DOM 时若宿主编码错,整个页面仍乱码
事情说清了就结束










