@charset "UTF-8" 必须位于CSS文件最开头,前面不能有任何字符(包括BOM、空格、换行或注释),否则浏览器将忽略该声明而回退至ISO-8859-1编码;同时HTTP响应头Content-Type中的charset优先级更高,需确保其值为text/css; charset=utf-8。

@charset "UTF-8" 必须是 CSS 文件的第一个字节
很多人加了 @charset "UTF-8"; 却还是乱码,根本原因是它前面藏了不可见字符:BOM、空格、换行、注释,甚至编辑器自动插入的 UTF-8 BOM(尤其在 Windows 下的 VS Code 或 Sublime 默认保存为 “UTF-8 with BOM” 时)。浏览器只要看到第一个字节不是 @,就直接忽略这条规则,退回到默认编码(通常是 ISO-8859-1)。
实操建议:
- 用十六进制编辑器(如 HxD、xxd)打开 CSS 文件,确认前三个字节不是
EF BB BF(即 UTF-8 BOM) - 在 VS Code 中:右下角点击编码 → “Save with Encoding” → 选 UTF-8(不要选 “UTF-8 with BOM”)
- Sublime Text:File → Save with Encoding → UTF-8
- 确保
@charset "UTF-8";是文件最开头,前面**不能有任何字符**,包括/* 注释 */或//
HTTP 响应头中的 charset 优先级高于 @charset
就算你写对了 @charset "UTF-8";,如果服务器返回的 HTTP 响应头里是 Content-Type: text/css; charset=gbk 或干脆没带 charset,浏览器仍会按响应头执行——此时 @charset 被无视。
检查方式:
- 打开 DevTools → Network → 找到你的 CSS 文件 → 点开 → Headers → Response Headers → 查
Content-Type - 常见错误值:
text/css(无 charset)、text/css; charset=iso-8859-1、application/x-css - Nginx 配置要加:
add_header Content-Type "text/css; charset=utf-8";(注意不是charset=UTF-8,大小写不敏感但推荐小写) - Apache 配置用:
AddType "text/css; charset=utf-8" css
HTML 的 对 CSS 文件无效
这是高频误解。 只影响 HTML 文档本身的解析,**完全不作用于外部 CSS 文件**。即使 HTML 和 CSS 都放在同一目录、用同一编辑器保存,只要 CSS 文件没声明编码或服务器没发对响应头,CSS 里的中文、Emoji、字体名(如 "微软雅黑")照样出错。
典型失败场景:
- CSS 里写了
font-family: "微软雅黑";,但浏览器渲染成 serif —— 因为微字被当成了两个 ISO-8859-1 字节,匹配失败 - 用
content: "✅";显示成方块或问号 —— 实际存储的是 UTF-8 多字节序列,但被当单字节读取 - 构建工具(如 Webpack/Vite)自动合并 CSS 时,若某个片段没带
@charset,整个合并后文件可能丢失编码声明
Unicode 转义是绕过编码问题的最稳方案
当无法 100% 控制文件保存方式、构建流程或服务器配置时,把非 ASCII 字符转成 Unicode 转义是最可靠 fallback。这不是“妥协”,而是规避所有编码链路风险的务实做法。
适用范围与写法:
- 字体名:
font-family: "\5FAE\8F6F\96C5\9ED1", sans-serif;(对应 “微软雅黑”) - content 内容:
.icon::before { content: "\1F4CB"; }(?) - 注意:Unicode 转义必须用反斜杠 + 4 位十六进制(U+XXXX),超出用
\{XXXXX}(CSS Color Level 4)或拆成代理对,但多数场景 4 位够用 - 别混用:不要写
content: "\1F4CB ✅";—— 混合写法会让后半段再次受编码影响
真正难的不是加一行 @charset,而是在构建、部署、CDN、本地 file:// 测试多个环节中,让每一个字节都按 UTF-8 解释。一旦某处漏掉,前面所有努力都会失效。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











