站点自定义:字体配置(以霞鹜文楷为例)
学习目标
- 理解 Quartz v5 站点的字体配置链路(两套系统 + 优先级)
- 掌握为站点引入 Google Fonts 之外 的字体(CDN 方式)
- 学会本地构建验证与提交发布流程
前置条件
- 完成 02_配置与本地构建
- 完成 03_自动化部署流水线
- 网站已成功上线(三分支策略可用)
1. 为什么要单独配置字体
Quartz 默认通过 Google Fonts 加载 theme.typography 中指定的字体(本教程默认 Noto Sans SC / JetBrains Mono)。但很多优秀的中文字体并不在 Google Fonts 上,例如:
- 霞鹜文楷(LXGW WenKai):开源楷体风格字体,仓库 lxgw/LxgwWenKai
- 直接把它填进
typography.header会怎样?og-image插件构建时去 Google Fonts 抓取会失败/警告,页面也不会有该字体
针对这类字体有两种接入方案:
| 方案 | 做法 | 优点 | 缺点 |
|---|---|---|---|
| CDN 引入(本教程采用) | 在 <head> 挂一张样式表,字体文件由 CDN 按需下发 | 改动小、维护简单 | 依赖第三方 CDN(jsDelivr) |
| 自托管 | 把 woff2 放进 quartz/static/,CSS 引用自己域名 | 完全离线、可控 | 需下载约 120 个子集文件 |
本项目采用 CDN 方案:字体包
lxgw-wenkai-webfont已发布到 npm,用 jsDelivr 直接引用即可:https://cdn.jsdelivr.net/npm/lxgw-wenkai-webfont@1.7.0/style.min.css
2. 先搞清字体配置链路
Quartz v5 有两套字体系统,容易混淆:
| 系统 | 位置 | 作用 |
|---|---|---|
| 核心主题 | quartz.config.yaml → theme.typography + theme.fontOrigin | 在 <head> 注入 Google Fonts 链接;variables.scss 据此生成 --titleFont/--headerFont/--bodyFont/--codeFont 变量(无 layer,优先级最高) |
| 字体插件 | @quartz-community/quartz-fonts(已内置启用) | 更细粒度控制(h1–h6 独立字体);生成的变量在 @layer quartz-fonts 中,优先级低于核心 |
因此结论是:在 custom.scss 里写一个 unlayered 的 :root 覆盖字体变量,一定生效(同优先级下位置靠后者胜出)。这正是本方案的核心思路。
3. 步骤一:在 <head> 注入 CDN 样式表
编辑 quartz/components/Head.tsx,在 Google Fonts 注入块之后加上:
{/* 霞鹜文楷(LXGW WenKai)webfont,通过 jsDelivr CDN 按 unicode-range 子集加载 */}
<link rel="preconnect" href="https://cdn.jsdelivr.net" crossOrigin="anonymous" />
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/lxgw-wenkai-webfont@1.7.0/style.min.css"
/>坑:为什么不能把
@import url("https://...")写进custom.scss?
Quartz 构建时会把所有 SCSS 打包成一个 CSS 文件,@import不在文件头部,会被 CSS 打包器拒绝,报错:
@import rules must precede all rules aside from @charset and @layer statements。
所以外部样式表必须走<head>的<link>。
4. 步骤二:覆盖字体变量
编辑 quartz/styles/custom.scss,在 @use 之后追加:
// 用霞鹜文楷覆盖站点字体(unlayered 变量,优先级最高)
:root {
--titleFont: "LXGW WenKai", system-ui, "Segoe UI", Roboto, sans-serif;
--headerFont: "LXGW WenKai", system-ui, "Segoe UI", Roboto, sans-serif;
--bodyFont: "LXGW WenKai", system-ui, "Segoe UI", Roboto, sans-serif;
--codeFont:
"LXGW WenKai Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
}字体族名以 webfont 包为准:正文
LXGW WenKai(400/700),代码LXGW WenKai Mono。另有LXGW WenKai Screen(屏幕优化版,独立包)。
5. 步骤三:修改 quartz.config.yaml
需要改三处:
theme:
fontOrigin: local # ① 核心系统不再注入 Google Fonts 链接
typography:
header: Noto Sans SC # ② 见下方说明
body: Noto Sans SC
code: JetBrains Mono- source: "@quartz-community/quartz-fonts"
enabled: true
options:
fontOrigin: local # ③ 插件也不再注入它自带的 Google 字体
title: "LXGW WenKai"
header: "LXGW WenKai"
body: "LXGW WenKai"
code: "LXGW WenKai Mono"② 为什么
theme.typography保留 Noto Sans SC 而不是改成 LXGW WenKai?
og-image插件渲染社交分享图(OG 图)时,会按theme.typography去 Google Fonts 抓取 TTF 嵌入图片。改成 LXGW WenKai 后:
- GitHub Actions(云端,网络正常)→ 返回 400 → 优雅降级(警告 + 用回退字体),构建仍成功;
- 本地网络不稳时 →
ECONNRESET→ 构建直接失败。
而页面显示字体由第 4 步的:root覆盖决定,与typography无关,所以保留 Noto Sans SC 最稳妥:OG 图正常、页面仍显示霞鹜文楷。
6. 步骤四:本地构建验证
npx quartz build
npx quartz build --serve # 预览 http://localhost:8080验证要点:
- HTML 头部:有 jsDelivr 字体链接,且不再有
fonts.googleapis.com链接; - CSS 变量:构建产物(
index-*.css)中--bodyFont等值为"LXGW WenKai",且出现在 Noto Sans SC 定义之后; - 浏览器实测:正文/标题计算样式为
"LXGW WenKai",document.fonts.check('16px "LXGW WenKai"')返回true。
7. 步骤五:提交发布
git add quartz.config.yaml quartz/components/Head.tsx quartz/styles/custom.scss
git commit -m "feat(fonts): 站点字体切换为霞鹜文楷(LXGW WenKai,CDN 方式)"
git push origin v5 # 受 ruleset 保护,需管理员/PR然后到 GitHub Actions 页面手动 Run workflow 触发 deploy.yml 发布到 gh-pages。
说明:站点访问者加载字体走 jsDelivr CDN,与你的本地网络/代理是否开启完全无关;发布流水线也在 GitHub 云端执行。唯一可能用到本地网络的是”本地构建”(见下节)。
8. 常见问题
8.1 本地构建报 ECONNRESET(连接被重置)
og-image 插件本地构建时要连 fonts.googleapis.com 抓 Noto Sans SC 的 TTF。网络抖动(或代理未开)时可能 ECONNRESET。
- 字体文件会缓存到
quartz/.quartz-cache/fonts/(gitignored),命中缓存后本地构建不再联网; - 若清了缓存或换了
typography,重试或确保能连 Google Fonts 即可; - GitHub Actions 在云端执行,有稳定网络,发布不受影响。
8.2 字体部分子集显示 unloaded
webfont 包把字体按 unicode-range 切成约 120 个子集,浏览器只下载当前页面用到的子集。DevTools 里看到大量 status=unloaded 是正常的。
8.3 想换回 Google Fonts 上的字体
改回 theme.fontOrigin: googleFonts、typography 填 Google Fonts 上的字体名,并移除 Head.tsx 里新增的 <link> 与 custom.scss 的覆盖块即可。
9. 拓展:自托管方案(可选)
若不想依赖 CDN,可把字体文件放进 quartz/static/fonts/(该目录会原样拷贝到站点根目录),步骤为:
- 从
lxgw-wenkai-webfont包批量下载files/lxgwwenkai-{regular,bold}-subset-*.woff2(约 238 个,5–6 MB); - 把 CSS 里相对路径
./files/改写成/fonts/; - 在
custom.scss里@import url("/fonts/lxgwwenkai-regular.css")或直接引用,并同样覆盖:root字体变量。
自托管后页面字体完全由 GitHub Pages 提供,无任何第三方依赖。