保哥笔记

WordPress 用一行 CSS 改默认中文字体为微软雅黑

保哥这些年帮人调过几十个 WordPress 站点,被吐槽最多的不是排版,也不是配色,而是“中文字体看着特别糊”。问题本质上不复杂:很多 WordPress 主题,尤其是国外作者写的主题,font-family 里只列了 ArialHelveticasans-serif 这一类英文字体栈,没指定中文字体,浏览器只能拿系统默认的宋体或者衬线字体来渲染中文,于是页面看起来就是“一股 Windows XP 的味道”。这篇笔记把保哥常年使用的一行 CSS 改字体方案、为什么这一行就够用、怎么避免破坏 Font Awesome 图标、以及多端字体适配的进阶玩法都整理出来,给同样被默认字体劝退的朋友抄作业。

一、为什么 WordPress 默认中文字体显得特别糊

保哥先把根因讲清楚。一个 WordPress 主题在 style.css 里通常这样写:

body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}

这串字体栈对英文渲染没有任何问题,但里面没有任何一项是中文字体。Windows 浏览器在拿不到中文字体声明时会回退到系统默认的中文字体,往往是“宋体”或者带衬线的渲染方式;macOS 会回退到“PingFang SC”,本身就好看;而很多老旧的国产 Chromium 套壳浏览器还会强行用一些自带字体,最终在不同访客那里呈现的样子千差万别。

站长侧能控制的只有一件事:在主题 CSS 里把中文字体显式声明出来,让所有现代浏览器都优先使用约定好的字体。保哥之所以选择微软雅黑,是因为它在 Windows 上覆盖率最高,macOS 用户会自动落到 PingFang SC,移动端会落到“苹方”或者“思源黑体”,整体观感会一致很多。

二、保哥常用的一行 CSS:原理拆解

保哥的“保哥笔记”主站这些年只用了一行 CSS 来修这个问题:

*:not([class*="icon"]):not(i) {
  font-family: "Segoe UI", "Microsoft Yahei", sans-serif !important;
}

看起来短,里面其实有四个值得拆开讲的细节。

第一个细节是 * 选择器。它会命中页面上所有元素,相当于一刀切地把字体替换成微软雅黑。比起一个个去找 bodyh1pa 来声明,这种写法最不容易遗漏。

第二个细节是 :not([class*="icon"])。这是用来把所有类名里包含 icon 的元素排除掉,最常见的就是 Font Awesome 的 fa-xxxicon-xxx、Material Icons 的 material-icons 等等。这些图标其实是用字体文件渲染的特殊字形,如果被强制改成微软雅黑,就会变成方块或者乱码。

第三个细节是 :not(i)。历史上 <i> 标签经常被用作图标占位(Bootstrap 早期主题、各种社交分享按钮都喜欢用 <i class="fa fa-xxx"></i>),单独把 i 标签排除掉是双保险。

第四个细节是 !important。WordPress 主题的 CSS 优先级各家写法不一致,有的主题在 body.home 里又重新声明了一遍 font-family,不加 !important 会被覆盖。加上之后就能稳定生效,副作用是后续如果想再改字体,需要明确知道是这一行在起作用。

三、把这行 CSS 放在哪里:三种推荐位置

保哥实测下来,下面三种位置都能让这行 CSS 生效,但适用场景不同。

第一种是 WordPress 自带的“外观 → 自定义 → 额外 CSS”。这是最推荐的方式,所有用户级 CSS 都集中在一处,主题更新不会丢失,关闭也只要把这行删掉即可。绝大多数情况选这个就够了。

第二种是子主题的 style.css。如果项目里已经做了子主题,可以把这行写到子主题里,配合版本控制更方便维护。但要注意子主题的 CSS 必须通过 wp_enqueue_style 正常加载,否则不会生效。

第三种是放进主题的 functions.php,用钩子动态注入:

// functions.php
add_action('wp_head', function () {
    echo '<style>*:not([class*="icon"]):not(i){font-family:"Segoe UI","Microsoft Yahei",sans-serif !important;}</style>';
}, 100);

这种做法适合需要根据用户登录状态、设备类型动态切换字体的场景,但写法上比直接放“额外 CSS”要繁琐,保哥不推荐入门用户这么干。

四、Font Awesome 与 emoji 的避坑要点

保哥被读者问过最多的一句话是:“按你那行写完之后,我的图标全变成方块了,是不是写错了?”大概率是漏掉了 :not 这部分。下面把容易踩坑的几种情况列出来。

如果使用 Font Awesome 6 的 SVG 模式,图标是 SVG 节点而不是字体字形,几乎不受 font-family 影响,可以放心。如果使用 Font Awesome 4/5 的字体模式,图标渲染依赖 FontAwesome 这个字体族,需要靠 :not([class*="icon"]) 排除,所以那一行不能省。

如果是阿里图标库 iconfont,它的类名通常是 iconfont icon-xxx,同样会被 [class*="icon"] 命中并排除,没问题。如果你用的是 Material Symbols,类名是 material-symbols-outlined,里面没有 icon 字符串,需要在 :not 里再加一项:

*:not([class*="icon"]):not(i):not([class*="material"]) {
  font-family: "Segoe UI", "Microsoft Yahei", sans-serif !important;
}

至于 emoji,主流系统会优先用系统自带的彩色 emoji 字体(Apple Color Emoji、Segoe UI Emoji 等),不会被 font-family 覆盖到普通文本字体上去,因此一般不需要额外处理。

五、面向多端与高分屏的进阶字体栈

保哥笔记早期就是这一行 CSS,但站点流量上来之后,移动端用户占比超过六成,单写微软雅黑就显得不够细腻。下面这套是保哥近两年在用的多端字体栈,给追求观感的同行参考:

*:not([class*="icon"]):not(i):not([class*="material"]) {
  font-family:
    -apple-system,
    BlinkMacSystemFont,
    "Segoe UI",
    "PingFang SC",
    "Hiragino Sans GB",
    "Microsoft Yahei",
    "Source Han Sans CN",
    sans-serif !important;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

这套写法的逻辑是:iOS / macOS 优先用系统的 -apple-system,自动落到“苹方”;Windows 优先用“Segoe UI”,中文落到“微软雅黑”;安卓优先用“思源黑体 CN”;其他情况再回退到 sans-serif

下面三行字体平滑相关的属性看似可有可无,但在高分屏(视网膜、2K、4K)上观感差距非常明显。-webkit-font-smoothing: antialiased 会让笔画更细更轻,text-rendering: optimizeLegibility 会让 Kerning 更自然。保哥实测在 macOS Safari 上开启之后,正文阅读疲劳感明显下降。

六、常见问题 FAQ

Q1:保哥,加了这行 CSS 之后我的代码块字体也变了,能让代码块继续用等宽字体吗?

可以。在那行 CSS 之后再加一条更具体的规则,把 precodekbdsamp 这几个标签恢复成等宽字体即可。例如:pre, code, kbd, samp { font-family: "Cascadia Code", Consolas, "Courier New", monospace !important; }。因为后写的 CSS 优先级相同时会覆盖前面的,所以代码块能正常显示等宽字体。

Q2:为什么我加了之后没生效,必须强刷才能看到?

这是浏览器和 CDN 缓存导致的。WordPress 自带的“额外 CSS”会通过 ?ver= 参数避免缓存,但如果你站点前面挂了 Cloudflare、又拉、阿里云 DCDN 这类服务,CSS 文件会被缓存几分钟到几十分钟。最快的做法是去 CDN 控制台清一次缓存,然后用无痕窗口访问。

Q3:用微软雅黑会不会有版权风险?

微软雅黑只随 Windows 系统授权,商业用途上把字体文件放到自己服务器分发是有风险的。但保哥这行 CSS 只是写了 font-family: "Microsoft Yahei",并没有把字体文件拷到服务器,访客是用自己电脑里 Windows 自带的字体来渲染,因此没有版权问题。如果是要把网页字体打包嵌入应用里分发,需要另行申请商用授权。