必须放在最前面,因为浏览器流式解析HTML时,前1024字节内若未遇到,将按HTTP响应头或系统默认编码(如GBK)解码,一旦出错则后续中文、emoji等全部乱码且不可逆。

为什么必须放在最前面
因为浏览器解析 HTML 是流式读取,前 1024 字节内若没遇到 <meta charset>,就会按 HTTP 响应头或系统默认编码(如 Windows 的 GBK)猜测解码——一旦猜错,后续所有中文、emoji、数学符号都会乱成方块或问号,且无法回退。哪怕后面写了 <meta charset="UTF-8"> 也无效。
常见错误现象:
– 页面标题显示为 “”
– <script></script> 中的中文注释变乱码
– CSS 里的中文类名失效
– alert("你好") 弹出空框或乱码字符
正确位置只有一种:
– 必须在 开始后、任何其他标签(包括 <title></title>、<link>、<script></script>)之前
– 不要加 /> 或 ,只写 <meta charset="UTF-8">
VS Code / Sublime / Notepad++ 怎么确保文件真正存为 UTF-8(无 BOM)
编辑器显示“UTF-8”不等于文件实际是 UTF-8。很多编辑器打开 GBK 文件时会自动识别并显示为“GBK”,但保存时若没手动选编码,仍会以原编码覆写——此时 <meta charset="UTF-8"> 就成了“假声明”。
立即学习“前端免费学习笔记(深入)”;
实操要点:
– VS Code:右下角点击编码名称(如 “GBK”),选 Save with Encoding → UTF-8(**不要选 UTF-8 with BOM**,BOM 会卡在文件开头,IE 和部分构建工具会跳过它导致 meta 失效)
– Sublime Text:菜单 File → Save with Encoding → UTF-8
– Notepad++:菜单 编码 → 转为 UTF-8 编码(不是“UTF-8-BOM”)
– 验证方法:用十六进制编辑器(如 HxD)打开文件,看开头三字节是否为 EF BB BF —— 如果是,说明带了 BOM,需重存
将 Markdown 文章转换为微信公众号兼容的纯 HTML 格式。当用户要求"转成微信格式"、"生成公众号文章 HTML"、"排版到微信草稿箱"、"微信粘贴格式"时触发。输出带内联样式的纯 HTML,微信编辑器可直接渲染,无需额外适配。支持标题、段落、列表、粗体、行内代码、表格、引用块、代码块、配图的完整转换。
HTTP 响应头 Content-Type 和 meta charset 冲突时谁生效
响应头优先级高于 <meta charset>。如果服务器返回 Content-Type: text/html; charset=GBK,即使 HTML 里写了 <meta charset="UTF-8">,浏览器也会用 GBK 解码,结果必乱。
排查步骤:
– 打开 Chrome DevTools → Network 标签 → 点 HTML 请求 → 查看 Response Headers 中的 Content-Type
– 若值为 text/html; charset=GBK 或不含 charset,说明服务端未配置
– Apache:在 .htaccess 加 AddDefaultCharset UTF-8
– Nginx:在 server 或 location 块加 charset utf-8;
– Node.js/Express:响应前加 res.set('Content-Type', 'text/html; charset=utf-8')
注意:file:// 协议下无响应头,此时完全依赖 <meta charset>,所以本地双击打开 HTML 必须靠它兜底。
外部 JS/CSS 文件的编码也要统一为 UTF-8
HTML 声明了 UTF-8,但引入的 <script src="app.js"></script> 或 <link href="style.css"> 如果本身是 GBK 编码,浏览器仍会按各自文件的 HTTP 响应头或 BOM 解码——它们和 HTML 的 charset 声明无关。
检查与修复:
– 对每个 JS/CSS 文件重复执行上一节的“编辑器保存为 UTF-8”操作
– 确保构建工具(Webpack/Vite)输出文件编码为 UTF-8(Vite 默认已是;Webpack 需确认 output.charset 或插件配置)
– 不要依赖 @charset "UTF-8"; 放在 CSS 文件开头——它仅对 CSS 解析器有效,不能替代文件实际编码
容易被忽略的一点:图标字体(.woff2)、SVG 内联文本、JSON 数据接口返回值,只要含中文,都必须是 UTF-8 编码。否则一个 emoji 或一个地名就可能让整页渲染失败。


















