用 CSS 变量做一套双主题色板
只改十几个 token,就能让深空和黎明两套皮肤共用一套组件。
FIG. 04 / 技术
双主题最难的不是「再写一套颜色」,而是保证两套颜色下组件的层级关系不变。我的做法是只暴露语义 token,组件永远不直接写颜色值。
Token 分三层
第一层是原始色,第二层是语义色,第三层才是组件。组件只认第二层,换主题时只换第一层。
:root {
--bg: #05070c;
--surface: rgba(255, 255, 255, 0.032);
--border: rgba(255, 255, 255, 0.085);
--text: #e9eff8;
--text-2: #98a7bd;
--accent: #6ee7f9;
}
html[data-theme='light'] {
--bg: #f4f7fb;
--surface: rgba(255, 255, 255, 0.72);
--border: rgba(11, 18, 32, 0.1);
--text: #0b1220;
--text-2: #485970;
--accent: #0e7490;
}
深色不是反色
浅色主题的底色偏冷灰,而不是纯白;强调色要加深,才能在浅底上有足够对比。深色主题的正文避免纯白,卡片只用 3% 左右的白,靠边框和间距分层。
一个容易忽略的细节
::selection、按钮文字、焦点轮廓都需要一个 --on-accent token。深色主题里它是近黑色,浅色主题里它必须是白色,否则按钮会变成「深色字压在深色底上」。
这套 token 目前有 14 个,改动成本很低,换肤只需要替换一组变量。
评论
待配置src/consts.ts里填入 Giscus 的repo与repoId,刷新后就会显示。 仓库需要是公开的,并在 GitHub 上开启 Discussions。