字体系统重做:脱离 Google Fonts,统一思源黑/宋,门面加霞鹜文楷
一、全部改走 jsdelivr 上的 Fontsource,不再依赖 Google Fonts
之前文章页的 Inter / Noto Sans SC / Playfair Display / Noto Serif SC
全部来自 fonts.googleapis.com —— 而文章页恰恰是最该稳的页面。
现在 5 份样式表都由 BaseLayout 顶部的 fontStylesheets 统一声明。
二、CJK 用可变字体(关键)
@fontsource-variable/noto-sans-sc 一份 CSS 覆盖 font-weight: 100 900,
不用为 400/500/600/700 各加载一份(那样是 4 × 105 KB = 420 KB)。
每份 CSS 内含约 100 条带 unicode-range 的 @font-face,浏览器只下载当前
页面命中的分包。完整思源黑体 3.3 MB / 101 个分包,一页通常只用到 100–300 KB。
三、层次:楷(门面点睛)> 宋(标题)> 黑(正文/UI)
- 正文/UI:思源黑体 Noto Sans SC Variable(两档都用)
- 标题:思源宋体 Noto Serif SC Variable
- 门面点睛:霞鹜文楷 LXGW WenKai(regular + bold)—— 用在站点名、
首页那句话、以及 --font-display-sans 覆盖的卡片标题
- 西文:Inter Variable(正文)+ Playfair Display(展示)
霞鹜文楷只在 fontProfile="interface" 的页面加载;文章页没加载它,
而 --font-display-sans 里它排在思源黑体前面,靠浏览器自动回退。
四、删掉鸿蒙 Sans
两档现在都用思源黑体,所以 body.font-profile-interface 那条按档覆盖字族的
规则删掉了。class 保留,它现在只用来决定是否加载文楷。
五、顺带修掉 --font-mono 断掉的回退链
原来只有 "Geist Mono", "Geist Mono Fallback" —— 这两个名字既没有 @font-face
也没装在机器上,等于整条回退链失效,浏览器退回默认字体(不是等宽)。
全站几十处 font-mono(时间线日期、偶得时间戳、内联代码、灯箱说明…)都在受影响。
补上 ui-monospace / SFMono-Regular / Menlo / Consolas / monospace。
体积账(gzip 后的样式表,和 .woff2 分包的实际下载是两回事)
文章页 62.5 KB -> 64.6 KB
门面 125.5 KB -> 127.4 KB
基本持平,换来摆脱 Google Fonts + 字体统一 + 多一款文楷
验证:pnpm build 退出码 0
- 文章页只加载 Inter + Playfair + 思源黑 + 思源宋;首页额外加载文楷两档
- 两类页面里 Google Fonts 与鸿蒙均已消失
- 产物 CSS 里 5 个字族名与 ui-monospace 回退均在
- 站点名与首页那句话的 class 已带 font-display-sans
- 字体文件实测可下载(jsdelivr 相对路径解析正常)
This commit is contained in:
@@ -299,6 +299,30 @@ sudo sysctl fs.inotify.max_user_watches=524288
|
|||||||
|
|
||||||
如果连空态提示都看不到,检查 `src/data/reading.json` 是否存在(这个文件要提交进 git)。
|
如果连空态提示都看不到,检查 `src/data/reading.json` 是否存在(这个文件要提交进 git)。
|
||||||
|
|
||||||
|
**想换字体 / 字体是从哪加载的**
|
||||||
|
|
||||||
|
全部由 `src/layouts/BaseLayout.astro` 顶部的 `fontStylesheets` 数组决定,
|
||||||
|
走 jsdelivr 上的 Fontsource 包(**不用 Google Fonts**,国内访问不稳):
|
||||||
|
|
||||||
|
| 层级 | 字体 | 用在哪 |
|
||||||
|
|---|---|---|
|
||||||
|
| 门面点睛(楷)| 霞鹜文楷 `LXGW WenKai` | 站点名、首页那句话、卡片标题 |
|
||||||
|
| 标题(宋)| 思源宋体 `Noto Serif SC Variable` | 文章标题、页面标题 |
|
||||||
|
| 正文/UI(黑)| 思源黑体 `Noto Sans SC Variable` | 文章正文、界面、按钮 |
|
||||||
|
| 西文 | `Inter Variable` + `Playfair Display` | 西文与数字、展示衬线 |
|
||||||
|
|
||||||
|
字族名的对应关系写在 `src/styles/global.css` 的 `--font-*` token 里。
|
||||||
|
改字体只需动这两处,不用碰组件。
|
||||||
|
|
||||||
|
两个要点:
|
||||||
|
|
||||||
|
- **CJK 用可变字体**(一份 CSS 覆盖 100–900 全字重),不要改成按字重加载 ——
|
||||||
|
那样每个字重一份 105 KB 的 CSS,四档就是 420 KB
|
||||||
|
- 每份 CSS 内含约 100 条带 `unicode-range` 的 `@font-face`,浏览器只下载当前页面
|
||||||
|
实际用到的那几个分包。完整思源黑体是 3.3 MB,但一页通常只命中 100–300 KB
|
||||||
|
- 霞鹜文楷**只在门面档加载**(`fontProfile="interface"`);文章页没加载它,
|
||||||
|
所以 `--font-display-sans` 里它排在思源黑体前面、由浏览器自动回退
|
||||||
|
|
||||||
**改了 markdown 插件却不生效**
|
**改了 markdown 插件却不生效**
|
||||||
|
|
||||||
Astro 会把渲染好的文章缓存到 `node_modules/.astro`,而这个缓存**只按 markdown
|
Astro 会把渲染好的文章缓存到 `node_modules/.astro`,而这个缓存**只按 markdown
|
||||||
|
|||||||
@@ -175,7 +175,7 @@ export function Hero() {
|
|||||||
*/}
|
*/}
|
||||||
<div className="hero-quote">
|
<div className="hero-quote">
|
||||||
<h1
|
<h1
|
||||||
className={`hero-typewriter font-sans ${HERO_SIZE_CLASSES} font-bold tracking-tight text-foreground leading-[1.15] min-h-[1.2em] whitespace-nowrap`}
|
className={`hero-typewriter font-display-sans ${HERO_SIZE_CLASSES} font-bold tracking-tight text-foreground leading-[1.15] min-h-[1.2em] whitespace-nowrap`}
|
||||||
>
|
>
|
||||||
{renderText()}
|
{renderText()}
|
||||||
</h1>
|
</h1>
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ const isCurrent = (href: string) =>
|
|||||||
class="w-full h-full object-cover"
|
class="w-full h-full object-cover"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<span class="text-foreground font-medium tracking-tight hidden sm:block">{site.name}</span>
|
<span class="font-display-sans text-foreground font-medium tracking-tight hidden sm:block">{site.name}</span>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
{/* 字号只在 lg 以上放大:768–1023 这段页眉本来就挤(导航 + 搜索框 + 主题按钮
|
{/* 字号只在 lg 以上放大:768–1023 这段页眉本来就挤(导航 + 搜索框 + 主题按钮
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"updatedAt": "2026-09-17T10:36:53.871Z",
|
"updatedAt": "2026-09-17T11:35:09.881Z",
|
||||||
"source": "weread",
|
"source": "weread",
|
||||||
"books": [
|
"books": [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -41,7 +41,36 @@ const {
|
|||||||
fontProfile = "reading",
|
fontProfile = "reading",
|
||||||
} = Astro.props as Props
|
} = Astro.props as Props
|
||||||
|
|
||||||
const useHarmonySans = fontProfile === "interface"
|
/** 门面档(首页、书架、专题、相册…)额外加载霞鹜文楷做点睛;文章页不需要 */
|
||||||
|
const isInterfaceProfile = fontProfile === "interface"
|
||||||
|
|
||||||
|
const FONTSOURCE_CDN = "https://cdn.jsdelivr.net/npm"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 字体清单。全部走 jsdelivr 上的 Fontsource 包,不再依赖 Google Fonts。
|
||||||
|
*
|
||||||
|
* - CJK 用**可变字体**:一份 CSS 覆盖 100–900 全字重,不用为 400/500/600/700
|
||||||
|
* 各下一份(那样是 4 × 105 KB)
|
||||||
|
* - 每份 CSS 内含约 100 条带 unicode-range 的 @font-face,浏览器只下载当前
|
||||||
|
* 页面实际用到的那几个分包,不是整包
|
||||||
|
* - 体积(gzip):文章页 ≈ 65 KB;门面再加文楷两档 ≈ 127 KB。
|
||||||
|
* 原来的 Google Fonts + 鸿蒙方案是 62.5 / 125.5 KB,基本持平
|
||||||
|
*/
|
||||||
|
const fontStylesheets = [
|
||||||
|
// 西文:正文与展示衬线
|
||||||
|
`${FONTSOURCE_CDN}/@fontsource-variable/inter@5/index.css`,
|
||||||
|
`${FONTSOURCE_CDN}/@fontsource/playfair-display@5/index.css`,
|
||||||
|
// 中文黑体(正文/UI)与宋体(标题)
|
||||||
|
`${FONTSOURCE_CDN}/@fontsource-variable/noto-sans-sc@5/index.css`,
|
||||||
|
`${FONTSOURCE_CDN}/@fontsource-variable/noto-serif-sc@5/index.css`,
|
||||||
|
// 门面点睛:霞鹜文楷(regular + bold)
|
||||||
|
...(isInterfaceProfile
|
||||||
|
? [
|
||||||
|
`${FONTSOURCE_CDN}/lxgw-wenkai-webfont@1.7.0/lxgwwenkai-regular.css`,
|
||||||
|
`${FONTSOURCE_CDN}/lxgw-wenkai-webfont@1.7.0/lxgwwenkai-bold.css`,
|
||||||
|
]
|
||||||
|
: []),
|
||||||
|
]
|
||||||
const canonicalUrl = canonical || Astro.url.toString()
|
const canonicalUrl = canonical || Astro.url.toString()
|
||||||
const resolvedOgTitle = ogTitle || title
|
const resolvedOgTitle = ogTitle || title
|
||||||
const resolvedOgDescription = ogDescription || description
|
const resolvedOgDescription = ogDescription || description
|
||||||
@@ -70,27 +99,10 @@ const resolvedTwitterDescription = twitterDescription || description
|
|||||||
<meta name="twitter:description" content={resolvedTwitterDescription} />
|
<meta name="twitter:description" content={resolvedTwitterDescription} />
|
||||||
<slot name="head" />
|
<slot name="head" />
|
||||||
<link rel="alternate" type="application/rss+xml" title="RSS" href="/rss.xml" />
|
<link rel="alternate" type="application/rss+xml" title="RSS" href="/rss.xml" />
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
{/* 字体全部走 jsdelivr 上的 Fontsource:CJK 用可变字体 + unicode-range 分包,
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
不再依赖 Google Fonts(国内访问不稳)。清单见上方 fontStylesheets。 */}
|
||||||
{useHarmonySans ? <link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin /> : null}
|
<link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin />
|
||||||
{useHarmonySans ? (
|
{fontStylesheets.map((href) => <link rel="stylesheet" href={href} />)}
|
||||||
<>
|
|
||||||
<link
|
|
||||||
rel="stylesheet"
|
|
||||||
href="https://cdn.jsdelivr.net/npm/harmonyos-sans-sc-webfont-splitted@1.1.0/dist/Regular.css"
|
|
||||||
/>
|
|
||||||
<link
|
|
||||||
rel="stylesheet"
|
|
||||||
href="https://cdn.jsdelivr.net/npm/harmonyos-sans-sc-webfont-splitted@1.1.0/dist/Semibold.css"
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
) : null}
|
|
||||||
<link
|
|
||||||
rel="stylesheet"
|
|
||||||
href={useHarmonySans
|
|
||||||
? "https://fonts.googleapis.com/css2?family=Playfair+Display:ital,wght@0,400..700;1,400..700&family=Noto+Serif+SC:wght@400..900&display=swap"
|
|
||||||
: "https://fonts.googleapis.com/css2?family=Inter:wght@400..700&family=Noto+Sans+SC:wght@400..700&family=Playfair+Display:ital,wght@0,400..700;1,400..700&family=Noto+Serif+SC:wght@400..900&display=swap"}
|
|
||||||
/>
|
|
||||||
<link rel="icon" href="/icon-light-32x32.png" media="(prefers-color-scheme: light)" />
|
<link rel="icon" href="/icon-light-32x32.png" media="(prefers-color-scheme: light)" />
|
||||||
<link rel="icon" href="/icon-dark-32x32.png" media="(prefers-color-scheme: dark)" />
|
<link rel="icon" href="/icon-dark-32x32.png" media="(prefers-color-scheme: dark)" />
|
||||||
<link rel="icon" href="/icon.svg" type="image/svg+xml" />
|
<link rel="icon" href="/icon.svg" type="image/svg+xml" />
|
||||||
@@ -212,7 +224,7 @@ const resolvedTwitterDescription = twitterDescription || description
|
|||||||
</script>
|
</script>
|
||||||
<ClientRouter />
|
<ClientRouter />
|
||||||
</head>
|
</head>
|
||||||
<body class:list={["bg-background text-foreground", { "font-profile-interface": useHarmonySans }]}>
|
<body class:list={["bg-background text-foreground", { "font-profile-interface": isInterfaceProfile }]}>
|
||||||
<slot />
|
<slot />
|
||||||
<ImageLightbox />
|
<ImageLightbox />
|
||||||
<script is:inline>
|
<script is:inline>
|
||||||
|
|||||||
+19
-9
@@ -163,12 +163,24 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@theme inline {
|
@theme inline {
|
||||||
--font-sans: "Inter", "Noto Sans SC", "PingFang SC", "Microsoft YaHei", system-ui, sans-serif;
|
/*
|
||||||
--font-display-sans: "HarmonyOS Sans SC", "Noto Sans SC", "PingFang SC", "Microsoft YaHei", sans-serif;
|
* 字体由 BaseLayout.astro 的 fontStylesheets 从 jsdelivr(Fontsource)加载,
|
||||||
--font-serif: "Noto Serif SC", "Source Han Serif SC", "Playfair Display", "Georgia", serif;
|
* 不再用 Google Fonts。CJK 都是可变字体,一份文件覆盖 100–900 全字重。
|
||||||
--font-serif-cn: "Noto Serif SC", "Source Han Serif SC", "Georgia", serif;
|
*
|
||||||
|
* 层次:楷(门面点睛)> 宋(标题)> 黑(正文/UI)
|
||||||
|
*/
|
||||||
|
--font-sans: "Inter Variable", "Noto Sans SC Variable", "PingFang SC", "Microsoft YaHei", system-ui, sans-serif;
|
||||||
|
/* 霞鹜文楷只在门面档加载;文章页没加载它,会自动退回思源黑体,所以它排第二位 */
|
||||||
|
--font-display-sans: "LXGW WenKai", "Noto Sans SC Variable", "PingFang SC", "Microsoft YaHei", sans-serif;
|
||||||
|
--font-serif: "Noto Serif SC Variable", "Source Han Serif SC", "Playfair Display", "Georgia", serif;
|
||||||
|
--font-serif-cn: "Noto Serif SC Variable", "Source Han Serif SC", "Georgia", serif;
|
||||||
--font-display-serif: "Playfair Display", "Georgia", serif;
|
--font-display-serif: "Playfair Display", "Georgia", serif;
|
||||||
--font-mono: "Geist Mono", "Geist Mono Fallback";
|
/*
|
||||||
|
* 原来只写了 "Geist Mono", "Geist Mono Fallback" —— 这两个名字既没有 @font-face
|
||||||
|
* 也没装在机器上,等于把 font-mono 的回退链断掉了,浏览器只能退回默认字体(不是等宽)。
|
||||||
|
* 全站几十处 font-mono(时间线日期、偶得时间戳、内联代码…)都受影响。
|
||||||
|
*/
|
||||||
|
--font-mono: "Geist Mono", ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;
|
||||||
--color-background: var(--background);
|
--color-background: var(--background);
|
||||||
--color-foreground: var(--foreground);
|
--color-foreground: var(--foreground);
|
||||||
--color-surface-subtle: var(--surface-subtle);
|
--color-surface-subtle: var(--surface-subtle);
|
||||||
@@ -245,10 +257,8 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
body.font-profile-interface,
|
/* 两档现在都用思源黑体,不再需要按档覆盖字族。
|
||||||
body.font-profile-interface .font-sans {
|
font-profile-interface 这个 class 保留 —— 它现在只决定是否额外加载霞鹜文楷。 */
|
||||||
font-family: "HarmonyOS Sans SC", "PingFang SC", "Microsoft YaHei", system-ui, sans-serif;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Custom smooth scrolling (avoid hash navigation animation) */
|
/* Custom smooth scrolling (avoid hash navigation animation) */
|
||||||
html {
|
html {
|
||||||
|
|||||||
Reference in New Issue
Block a user