Glance 主题系统完全指南:内置配色预设、HSL 颜色配置与主题切换原理
【免费下载链接】glanceA self-hosted dashboard that puts all your feeds in one place项目地址: https://gitcode.com/GitHub_Trending/gla/glance
Glance 是一款自托管的信息聚合面板,其主题能力建立在「配置文件中声明式地定义 HSL 颜色变量」这一核心机制之上。docs/themes.md 收录了官方内置的全部 15 套配色预设(11 套深色、3 套浅色),每一套都可以直接复制进glance.yml使用,也可以作为你打造自定义外观的起点。读完本文,你将掌握主题配置中每个字段的含义与取值约束、深色/浅色两套预设体系、自定义主题的接入方法,以及「配置生成 CSS 变量 → 页面热更新 → 前端实时切换」的底层实现链路。
一、主题配置:在顶层theme:块中声明
Glance 的主题全部写在配置文件的顶层theme:节点下。它不是一个独立系统,而是与pages、widgets同一层级的配置结构,因此修改主题和修改布局、挂载小组件完全一致,统一走 YAML 配置热加载。
以文档中「Teal City」这一套深色主题为例,最小配置块如下:
theme: background-color: 225 14 15 primary-color: 157 47 65 contrast-multiplier: 1.1与多数面板“直接填十六进制色值”不同,Glance 主题的全部颜色字段都采用空格分隔的 HSL 三元组(H S L),而不是#RRGGBB。这样做的工程意义在于:整个界面的文字、分割线、进度条、弹层背景等大量衍生色,都围绕同一色相做亮度/饱和度偏移生成,只要换一个背景色相,整套 UI 就能在视觉上保持统一(见 internal/glance/static/css/main.css 中基于--bgh/--bgs/--bgl的大量hsl(var(--bghs), ...)派生计算)。
全部可用字段
| 字段 | 类型 | 含义 | 取值范围/说明 |
|---|---|---|---|
background-color | HSL | 页面主背景色 | H:0–360;S、L:0–100 |
primary-color | HSL | 主强调色(链接、按钮、边框、选中态等) | 同上 |
positive-color | HSL | 正向语义色(上升、在线、成功等) | 同上 |
negative-color | HSL | 负向语义色(下降、错误、告警等) | 同上 |
light | bool | 声明为浅色主题 | 影响data-scheme与配色推导方向 |
contrast-multiplier | float | 文字对比度倍率 | 内置预设使用 1.0–1.5 |
text-saturation-multiplier | float | 文字饱和度倍率 | 内置预设中为 0.5,用于压制亮色背景上的文字饱和度 |
这些字段直接对应源码中 internal/glance/theme.go 的themeProperties结构体,YAML tag 与上表字段一一对应。颜色值在解析时经过严格校验:hslColorField.UnmarshalYAML通过正则解析三元组,并逐一检查hue ≤ 360、saturation ≤ 100、lightness ≤ 100,越界会给出包含具体 YAML 行号的报错(见 internal/glance/config-fields.go)。正则也兼容hsla(...)包裹或逗号分隔的写法,但官方预设统一使用纯数字空格分隔。
字段是如何变成样式的
每个主题块在初始化时,都会被丢进模板 internal/glance/templates/theme-style.gotmpl,动态生成一段 CSS 变量声明(只输出配置过的字段):
:root { --bgh: 225; --bgs: 14%; --bgl: 15%; --cm: 1.1; --color-primary: hsl(157.0, 47.0%, 65.0%); --color-positive: ...; --color-negative: ...; }这段 CSS 由 internal/glance/theme.go 的themeProperties.init()渲染,随后被内联到每个页面的<style id="theme-style">标签中(见 internal/glance/templates/document.html)。background-color还会被转换成十六进制,用于浏览器地址栏的theme-colormeta 与 PWA 清单中的应用背景色。
二、深色主题预设(Dark)
以下 11 套深色预设均直接取自 docs/themes.md,配合文档目录 docs/images/themes/ 中的官方截图使用。
Teal City
theme: background-color: 225 14 15 primary-color: 157 47 65 contrast-multiplier: 1.1Catppuccin Frappe
theme: background-color: 229 19 23 contrast-multiplier: 1.2 primary-color: 222 74 74 positive-color: 96 44 68 negative-color: 359 68 71Catppuccin Macchiato
theme: background-color: 232 23 18 contrast-multiplier: 1.2 primary-color: 220 83 75 positive-color: 105 48 72 negative-color: 351 74 73Catppuccin Mocha
theme: background-color: 240 21 15 contrast-multiplier: 1.2 primary-color: 217 92 83 positive-color: 115 54 76 negative-color: 347 70 65Camouflage
theme: background-color: 186 21 20 contrast-multiplier: 1.2 primary-color: 97 13 80Gruvbox Dark
theme: background-color: 0 0 16 primary-color: 43 59 81 positive-color: 61 66 44 negative-color: 6 96 59Kanagawa Dark
theme: background-color: 240 13 14 primary-color: 51 33 68 negative-color: 358 100 68 contrast-multiplier: 1.2Tucan
theme: background-color: 50 1 6 primary-color: 24 97 58 negative-color: 209 88 54Dracula
theme: background-color: 231 15 21 primary-color: 265 89 79 contrast-multiplier: 1.2 positive-color: 135 94 66 negative-color: 0 100 67Shades of Purple
theme: background-color: 243 33 25 contrast-multiplier: 1.2 primary-color: 50 100 49 positive-color: 98 82 71 negative-color: 12 77 52Neon Pink
theme: background-color: 240 27 11 contrast-multiplier: 1.5 primary-color: 321 100 71 positive-color: 165 78 51 negative-color: 360 100 71三、浅色主题预设(Light)
浅色预设与深色预设的结构完全一致,唯一的差别是必须显式声明light: true。该标志会直接影响渲染结果:HTML 根节点的data-scheme属性会被标记为light,CSS 中大量calc(var(--scheme) ...)推导式的运算方向也会随之反转,从而在浅色背景下自动生成对比度足够的深色文字,而不必逐项手工指定文字颜色。
Catppuccin Latte
theme: light: true background-color: 220 23 95 contrast-multiplier: 1.0 primary-color: 220 91 54 positive-color: 109 58 40 negative-color: 347 87 44Peachy
theme: light: true background-color: 28 40 77 primary-color: 155 100 20 negative-color: 0 100 60 contrast-multiplier: 1.1 text-saturation-multiplier: 0.5注意 Peachy 额外使用了text-saturation-multiplier: 0.5:在低饱和度的粉色背景上,如果文字继续沿用背景的相近色相,会显得刺眼、难读,因此把文字饱和度压缩一半。这与内置的浅色默认主题行为一致——text-saturation-multiplier的默认生效值正是 0.5(见下文源码分析)。
Zebra
theme: light: true background-color: 0 0 95 primary-color: 0 0 10 negative-color: 0 90 50四、从源码看主题的默认值与双主题机制
你没写颜色时会发生什么
themeProperties.init()中有一个重要兜底逻辑:当整个theme:块完全为空时,BackgroundColorAsHex会被设置为#151519(见 internal/glance/theme.go),保证没有任何主题配置也能渲染出可用的深色外观。而在 YAML 层,颜色字段全部是指针类型、默认nil,模板只有在字段非空时才会输出对应的 CSS 变量——这正是“最小主题块只需写三个字段”也能正常运行的原因。
default-dark 与 default-light
Glance 的“默认主题”概念是成对出现的。在应用初始化阶段(internal/glance/glance.go),只要未关闭主题选择器,就会向内部预设集合注入两套兜底主题:
default-dark:完全空白配置(themeProperties{}),即依赖上文#151519兜底与 CSS 默认色;default-light:硬编码的浅色默认主题,背景240 13 95、主色230 100 30、负向色0 70 50、contrast-multiplier: 1.3、text-saturation-multiplier: 0.5。
随后,你在顶层theme:块中写的颜色,会成为页面无 Cookie 状态下的“默认”外观;而default-dark/default-light这两套只出现在前端主题切换器里。如果你的顶层theme:恰好与其中某套完全相同,初始化代码会跳过重复注入,避免切换器中出现两个看起来一样的选项。
运行时切换主题:Cookie + 专用路由
Glance 允许访问者在不改动配置的前提下临时切换外观。其实现要点如下:
- 页面加载时,internal/glance/glance.go 的
populateTemplateRequestData会读取名为theme的 Cookie,命中内部预设集合中的某个键后,就用该预设替换当前渲染主题; - 主题切换器(页面右上角的下拉控件,见 internal/glance/templates/page.html)的每个选项都调用
POST /api/set-theme/{key}接口,路由注册于 internal/glance/glance.go; - internal/glance/theme.go 的
handleThemeChangeRequest会先校验key是否存在于预设集合中(default键则映射回配置主块),随后写回有效期 2 年的 Cookie,并直接把该预设的 CSS 作为text/css响应体返回,同时通过X-Scheme响应头声明明暗属性,前端拿到后即可完成无刷新换肤。
presets:为切换器注册你自己的主题
theme:块还支持一个presets映射,用于把多套主题同时注册进右上角的主题切换器。该结构在 internal/glance/config.go 中声明,类型为保序的 YAML 映射(orderedYAMLMap,实现见同文件 internal/glance/config.go),并在初始化时与内置的 default 系列合并。每套预设与顶层主题拥有完全相同的字段。例如:
theme: background-color: 231 15 21 # 作为默认主题 primary-color: 265 89 79 presets: my-dark: background-color: 250 40 10 primary-color: 20 90 55 contrast-multiplier: 1.3 my-light: light: true background-color: 220 30 90 primary-color: 220 80 45保存配置后,切换器(其渲染模板见 internal/glance/templates/theme-preset-preview.html,会为每套预设生成一个带主色/正负语义色圆点的小色卡预览)就会出现my-dark、my-light两个可点击项。
何时关闭主题切换器与追加自定义 CSS
theme:块还有两个配套字段:
disable-picker: true:关闭右上角的主题选择器,也意味着不注入 default-dark/default-light 预设(代码见 internal/glance/glance.go),且 Cookie 换肤逻辑整体失效,所有人看到的都是顶层theme:的外观;custom-css-file:指向一个 CSS 文件的路径,该文件的全部内容会作为页面额外的<style>注入,用来在主题变量之外追加更细粒度的定制样式。
五、把一套预设真正跑起来
官方预设已经保证了开箱即用,实践中有三种用法:
- 整块替换:把上面任一 YAML 块整体放进
glance.yml,替换掉已有的theme:内容,刷新页面即生效; - 只改局部:保留自己的
theme:,仅借鉴某套预设中的单个字段值,例如把 Teal City 的contrast-multiplier: 1.1复制到自己的主题上增强文字对比; - 注册进切换器:用上文的
presets语法同时注册多套官方配色,让访问者随时切换。
想进一步查看这些预设当前生效效果的完整截图,可打开文档目录 docs/images/themes/ 下的同名图片逐一对照;配置文件的整体结构示例见仓库根目录的 docs/glance.yml,关于全部顶层配置项(含theme)的说明可继续阅读 docs/configuration.md。
六、小结:主题即配置,换肤即换 CSS 变量
总结 Glance 主题系统的完整工作链条:theme:YAML →themeProperties结构体解析与 HSL 数值校验 → theme-style.gotmpl 渲染出:rootCSS 变量 → 内联进 document.html 的<style id="theme-style">→ 交由 main.css 中基于色相派生的大量子规则完成整页配色;同时通过「Cookie +POST /api/set-theme/{key}+ presets 预设集合」支撑起前端实时换肤。
对使用者而言,掌握了docs/themes.md里的全部字段与 15 套官方预设,就等于掌握了给 Glance 换装的全部素材;对想要深度定制的人来说,官方预设中那些“只写了 3–4 个颜色就能得到完整精致 UI”的配置,恰恰是理解其同色相派生配色引擎的最好范本。
【免费下载链接】glanceA self-hosted dashboard that puts all your feeds in one place项目地址: https://gitcode.com/GitHub_Trending/gla/glance
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考