根本原因是nginx未在http响应头中声明charset=utf-8,导致浏览器按系统locale(如gbk)错误解析utf-8字节流,产生涓枃、䏿–‡等乱码;@charset仅对本地file://有效,nginx下必须通过charset utf-8指令显式设置响应头。

不是 CSS 没加载,是 Nginx 用 Latin-1 解析了 UTF-8 字节流——根本原因在于 Nginx 默认不声明响应编码,浏览器退回到系统 locale(如 Windows 的 GBK)去解码,把一个中文的 3 字节 UTF-8 序列当成了 3 个单字节字符处理,结果就是 涓枃、䏿–‡ 这类典型乱码。
为什么 @charset "UTF-8" 在 Nginx 下完全失效
@charset 只在浏览器直接读取 CSS 文件时起作用(比如本地 file://),而 Nginx 是 HTTP 服务器,它决定浏览器怎么解析 CSS 的唯一权威依据是 HTTP 响应头中的 Content-Type。只要响应头没带 charset=utf-8,哪怕 CSS 文件第一行写着 @charset "UTF-8",浏览器也直接忽略。
- Nginx 默认返回
Content-Type: text/css,不带charset参数 - Chrome/Firefox 遇到无 charset 的
text/css,会 fallback 到系统 locale(Windows 下常为 GBK) - Linux/macOS 服务器上 Nginx 本身不改写响应头,也不会自动补 charset
- 即使你确认 CSS 文件是 UTF-8 without BOM、
@charset位置绝对正确,也救不了
必须在 Nginx 配置中显式设置 charset
只需在 http、server 或 location 块中加一行:charset utf-8;。但要注意生效范围和覆盖逻辑:
- 放在
http块:全局生效,但可能被下游 location 覆盖 - 放在
location ~* \.css$块:精准控制 CSS 响应头,推荐 - 必须配合
charset_types才能对非默认 MIME 类型生效(如application/javascript) - 错误写法:
add_header Content-Type "text/css; charset=utf-8";—— 这会覆盖 Nginx 原生的Content-Type,可能导致 MIME 类型丢失
正确配置示例:
location ~* \.css$ {
charset utf-8;
expires 30d;
}
别漏掉静态资源路径里的中文文件名
@charset 和 charset utf-8 只管 CSS 文件“内容”的编码,不管 URL 路径里的中文怎么解码。如果 Bootstrap 引用了 url("图标.svg") 或 @import "按钮.css",而这些文件名含中文,Nginx 默认按字节匹配——但客户端请求时已做 UTF-8 Percent-encoding(如 %E6%8C%89%E9%92%AE.css),Nginx 若未在内部以 UTF-8 视角处理 URI,就可能匹配失败或返回 404。
- Linux 文件系统不强制文件名编码,
ls -b查看原始字节,确认是否为 UTF-8 编码序列 - 避免路径含中文是最稳妥的做法;若必须使用,确保上传环境统一为 UTF-8,并在 Nginx 中启用
charset utf-8;(它也影响 URI 解码上下文) - Windows 环境下通过 SMB 或 FTP 上传的中文文件名,很可能实际是 GBK 字节,Nginx 匹配不到——此时需用
convmv转换文件名编码
最容易被忽略的是:Nginx 的 charset 指令不会自动修复已损坏的 CSS 文件字节。如果文件本身是 UTF-8 with BOM,或被多次错误转码过,即便响应头正确,内容仍会错乱。先用 xxd style.css | head -1 确认开头三字节不是 ef bb bf,再检查 Nginx 配置,顺序不能反。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











