☰
Fantastic-admin 主题 CSS 变量结构全解析:从 shadcn Token 到框架专属 `--g-*` 变量的定制实践
2026/10/3 1:42:32 网站建设 项目流程
  • 前端
  • AI 技能

【免费下载链接】basic

⭐⭐⭐⭐⭐ 面向 AI 编程的管理系统框架,兼容PC、移动端。AI-oriented management system framework, compatible with PC and mobile device.

项目地址:https://gitcode.com/GitHub_Trending/ba/basic
点击查看免费下载

本文档讲解 Fantastic-admin(本仓库中由packages/themes/index.ts导出的lightTheme/darkTheme定义的)主题体系的核心骨架:它由shadcn 标准 token与框架专属--g-*token两类 CSS 变量组成,前者控制组件级颜色,后者控制布局区域(头部、主侧边栏、次侧边栏、标签栏、工具栏)的配色。读完本文,你将掌握这两类变量的完整清单与取值规范、明暗两套主题在 5 个关键维度上的差异设计、完整暗色--g-*模板,以及它们如何通过 UnoCSS 预处理器注入页面并被布局组件实际消费的底层链路,从而能够自行创建和定制符合规范的主题配色。

一、主题变量的两类构成

Fantastic-admin 的主题不是单一的颜色变量表,而是由两类职责清晰的变量共同组成:

  1. shadcn 标准 token— 通用设计系统变量,控制按钮、卡片、输入框、弹出层等组件的颜色语义,与社区 shadcn/ui 生态保持兼容。
  2. 框架专属 token(--g-*)— 控制布局区域颜色,例如头部(Header)、主导航(MainSidebar)、次导航(SubSidebar)、标签栏(Tabbar)、工具栏(Toolbar)、主内容区(MainArea),是 Fantastic-admin 对通用 token 的布局级扩展。

这种分层设计的价值在于:shadcn 标准 token 负责"组件语义"(什么状态该用什么色),--g-*负责"区域归属"(哪个布局区域引用哪个语义色),二者通过oklch(var(--xxx))这种引用式赋值串联起来,使得改一个语义色即可联动整个布局。

源码佐证:主题定义与注入位置

  • 主题定义文件:packages/themes/index.ts,以as const导出lightTheme与darkTheme,跨所有应用共享;
  • 注入实现:uno.config.ts 中名为unocss-preset-shadcn的 UnoCSS preset,通过entriesToCss(Object.entries(lightTheme))把变量写入:root,通过entriesToCss(Object.entries(darkTheme))写入.dark,并在configDeps中声明对packages/themes/index.ts的依赖,使主题文件变更可被构建工具自动追踪。
// uno.config.ts 中注入主题变量的核心片段 toArray(':root').map(root => `${root}{color-scheme:light;${entriesToCss(Object.entries(lightTheme))}}`).join(''), toArray('.dark').map(root => `${root}{color-scheme:dark;${entriesToCss(Object.entries(darkTheme))}}`).join(''),

二、shadcn 标准 Token 详解

shadcn 标准 token 的取值格式为'L C H'——OKLCH 三个数值,用空格分隔,不含oklch()包裹(例如'1 0 0'即纯白oklch(1 0 0))。

变量作用
--background页面主背景色
--foreground主文字颜色
--card卡片背景色(通常同 background)
--card-foreground卡片文字颜色
--popover弹出层背景色
--popover-foreground弹出层文字颜色
--primary主色调(按钮、高亮、激活状态)
--primary-foreground主色上的文字颜色
--secondary次要色(次要按钮、标签背景)
--secondary-foreground次要色上的文字颜色
--muted静音色(禁用状态、次要背景)
--muted-foreground静音色上的文字颜色
--accent强调色(hover 状态背景)
--accent-foreground强调色上的文字颜色
--destructive危险/错误色(删除、警告)
--border边框颜色
--input输入框边框颜色
--ring焦点环颜色(通常同 primary)

从 uno.config.ts 可以看到,这些 token 被映射为 UnoCSS 主题色板(background、foreground、primary、secondary、muted、accent、destructive、border、input、ring等),组件中可直接使用bg-primary、text-muted-foreground这类工具类,其底层色值即oklch(var(--xxx))。

默认色值参考(当前仓库实际值)

明色主题(packages/themes/index.ts):

'--background': '1 0 0', // oklch(1 0 0) 纯白 '--foreground': '0.145 0 0', // 近黑文字 '--card': '1 0 0', '--card-foreground': '0.145 0 0', '--popover': '1 0 0', '--popover-foreground': '0.145 0 0', '--primary': '0.205 0 0', // 深色主按钮 '--primary-foreground': '0.985 0 0', '--secondary': '0.97 0 0', '--secondary-foreground': '0.205 0 0', '--muted': '0.97 0 0', '--muted-foreground': '0.556 0 0', '--accent': '0.97 0 0', '--accent-foreground': '0.205 0 0', '--destructive': '0.577 0.245 27.325', // 红色系,通常保持不变 '--border': '0.922 0 0', '--input': '0.922 0 0', '--ring': '0.708 0 0',

三、框架专属 Token(--g-*)

框架专属 token 的取值格式为'oklch(L C H)'或'oklch(var(--xxx))'——含oklch()包裹,且通常直接引用 shadcn 标准 token,形成"语义色 → 区域色"的引用链。

变量作用
--g-main-area-bg主内容区域背景
--g-header-bg顶部背景
--g-header-color顶部文字颜色
--g-header-menu-color顶部导航菜单项文字颜色
--g-header-menu-hover-bg顶部导航菜单项 hover 背景
--g-header-menu-hover-color顶部导航菜单项 hover 文字颜色
--g-header-menu-active-bg顶部导航菜单项激活背景
--g-header-menu-active-color顶部导航菜单项激活文字颜色
--g-main-sidebar-bg主侧边栏背景
--g-main-sidebar-menu-color主侧边栏导航菜单文字颜色
--g-main-sidebar-menu-hover-bg主侧边栏导航菜单 hover 背景
--g-main-sidebar-menu-hover-color主侧边栏导航菜单 hover 文字颜色
--g-main-sidebar-menu-active-bg主侧边栏导航菜单激活背景
--g-main-sidebar-menu-active-color主侧边栏导航菜单激活文字颜色
--g-sub-sidebar-bg次侧边栏背景
--g-sub-sidebar-menu-color次侧边栏导航菜单文字颜色
--g-sub-sidebar-menu-hover-bg次侧边栏导航菜单 hover 背景
--g-sub-sidebar-menu-hover-color次侧边栏导航菜单 hover 文字颜色
--g-sub-sidebar-menu-active-bg次侧边栏导航菜单激活背景
--g-sub-sidebar-menu-active-color次侧边栏导航菜单激活文字颜色
--g-tabbar-bg标签栏背景
--g-tabbar-tab-color标签项文字颜色
--g-tabbar-tab-hover-bg标签项 hover 背景
--g-tabbar-tab-hover-color标签项 hover 文字颜色
--g-tabbar-tab-active-bg标签项激活背景
--g-tabbar-tab-active-color标签项激活文字颜色
--g-toolbar-bg工具栏背景

布局组件如何消费这些变量

从源码结构看,每个布局区域组件都直接以 CSS 变量声明其样式,主题换色无需改动组件逻辑:

  • 主内容区:apps/core/src/layouts/index.vue 中background-color: var(--g-main-area-bg);
  • 头部:apps/core/src/layouts/components/Header/index.vue 中background-color: var(--g-header-bg),菜单项通过text-[var(--g-header-menu-color)]、hover:(text-[var(--g-header-menu-hover-color)] bg-[var(--g-header-menu-hover-bg)])、bg-[var(--g-header-menu-active-bg)]等工具类引用对应状态变量;
  • 主侧边栏:apps/core/src/layouts/components/MainSidebar/index.vue 中声明color: var(--g-main-sidebar-menu-color)、background-color: var(--g-main-sidebar-bg)及各 hover/active 状态;
  • 次侧边栏:apps/core/src/layouts/components/Menu/item.vue 中通过text-[var(--g-sub-sidebar-menu-color)]、bg-[var(--g-sub-sidebar-menu-active-bg)]消费次导航变量;
  • 标签栏:apps/core/src/layouts/components/Topbar/Tabbar/index.vue 中background-color: var(--g-tabbar-bg);
  • 工具栏:apps/core/src/layouts/components/Topbar/Toolbar/index.vue 中bg-[var(--g-toolbar-bg)]。

四、明色与暗色的 5 处关键差异

明色与暗色主题除了色值深浅不同外,在--g-*变量的取值策略上存在 5 处刻意设计的差异。理解这些差异是手写暗色主题模板的前提。

差异一:菜单激活状态

明色激活态使用primary(高对比、品牌感),暗色激活态改用accent(更柔和的明度差,避免暗色下高亮过曝):

// 明色 '--g-header-menu-active-bg': 'oklch(var(--primary))', '--g-header-menu-active-color': 'oklch(var(--primary-foreground))', // 暗色 '--g-header-menu-active-bg': 'oklch(var(--accent))', '--g-header-menu-active-color': 'oklch(var(--accent-foreground))',

同样适用于--g-main-sidebar-menu-active-*和--g-sub-sidebar-menu-active-*,即主导航与次导航菜单的激活态遵循同一规则。

差异二:主内容区背景

明色下主内容区背景略深于页面背景,形成内容区与背景的层次感;暗色下则与背景相同,避免暗色界面层次过多造成视觉负担:

// 明色:略深于背景,形成层次感 '--g-main-area-bg': 'oklch(0.9612 0 0)', // 暗色:与背景相同,避免过多层次 '--g-main-area-bg': 'oklch(var(--background))',

差异三:标签栏 hover 背景

// 明色 '--g-tabbar-tab-hover-bg': 'oklch(var(--border))', // 暗色 '--g-tabbar-tab-hover-bg': 'oklch(var(--accent) / 50%)',

暗色使用accent并叠加 50% 透明度,让 hover 反馈更克制。

差异四:标签栏激活背景

// 明色 '--g-tabbar-tab-active-bg': 'oklch(var(--background))', // 暗色 '--g-tabbar-tab-active-bg': 'oklch(var(--secondary))',

差异五:菜单颜色引用

菜单项默认文字颜色,明色引用accent-foreground,暗色引用muted-foreground——暗色下文字弱化,突出可读层级:

// 明色:使用 accent-foreground '--g-header-menu-color': 'oklch(var(--accent-foreground))', '--g-header-menu-hover-color': 'oklch(var(--accent-foreground))', // 暗色:使用 muted-foreground '--g-header-menu-color': 'oklch(var(--muted-foreground))', '--g-header-menu-hover-color': 'oklch(var(--muted-foreground))',

五、完整暗色--g-*模板

以下是可直接复制使用的完整暗色--g-*变量模板(与 packages/themes/index.ts 中darkTheme的实现一致):

dark: { // shadcn token ... '--g-main-area-bg': 'oklch(var(--background))', '--g-header-bg': 'oklch(var(--background))', '--g-header-color': 'oklch(var(--foreground))', '--g-header-menu-color': 'oklch(var(--muted-foreground))', '--g-header-menu-hover-bg': 'oklch(var(--muted))', '--g-header-menu-hover-color': 'oklch(var(--muted-foreground))', '--g-header-menu-active-bg': 'oklch(var(--accent))', '--g-header-menu-active-color': 'oklch(var(--accent-foreground))', '--g-main-sidebar-bg': 'oklch(var(--background))', '--g-main-sidebar-menu-color': 'oklch(var(--muted-foreground))', '--g-main-sidebar-menu-hover-bg': 'oklch(var(--muted))', '--g-main-sidebar-menu-hover-color': 'oklch(var(--muted-foreground))', '--g-main-sidebar-menu-active-bg': 'oklch(var(--accent))', '--g-main-sidebar-menu-active-color': 'oklch(var(--accent-foreground))', '--g-sub-sidebar-bg': 'oklch(var(--background))', '--g-sub-sidebar-menu-color': 'oklch(var(--muted-foreground))', '--g-sub-sidebar-menu-hover-bg': 'oklch(var(--muted))', '--g-sub-sidebar-menu-hover-color': 'oklch(var(--muted-foreground))', '--g-sub-sidebar-menu-active-bg': 'oklch(var(--accent))', '--g-sub-sidebar-menu-active-color': 'oklch(var(--accent-foreground))', '--g-tabbar-bg': 'oklch(var(--background))', '--g-tabbar-tab-color': 'oklch(var(--accent-foreground) / 50%)', '--g-tabbar-tab-hover-bg': 'oklch(var(--accent) / 50%)', '--g-tabbar-tab-hover-color': 'oklch(var(--accent-foreground) / 50%)', '--g-tabbar-tab-active-bg': 'oklch(var(--accent))', '--g-tabbar-tab-active-color': 'oklch(var(--foreground))', '--g-toolbar-bg': 'oklch(var(--background))', },

对照第 4 节可以逐条验证:暗色模板全部采用accent激活、muted-foreground菜单文字、background同源的主内容区,并且标签栏 hover/激活使用带透明度的accent系取值。

六、如何基于本结构创建自定义主题

结合 skills/fa-theme-customizer/SKILL.md 描述的工作流,自定义主题的实操路径如下:

  1. 确认设计风格:若没有明确的品牌色,可参考 skills/fa-theme-customizer/references/design-styles.md 中收录的 20+ 种设计风格配色(吉卜力、赛博朋克、莫兰迪、北欧极简、瑞士国际主义等),或 tweakcn 社区主题的 shadcn CSS 变量。
  2. 生成 OKLCH 色值:框架使用 OKLCH 色彩空间,shadcn token 格式为L C H(不含oklch()包裹)。转换规则参考:
    • 明色背景:1 0 0(纯白)或接近白色的暖/冷色调;
    • 暗色背景:0.141 0.005 285.823(默认深灰)或更深的色调;
    • 主色(primary):明色通常比暗色亮度(L 值)高 0.05~0.1。
  3. 替换主题文件:在 packages/themes/index.ts 中替换lightTheme与darkTheme,格式严格遵循第 2、3 节的变量清单与第 5 节的暗色模板;类型由as const自动推断,无需手动更新类型定义。
  4. 始终同时生成明色与暗色两套主题,并套用第 4 节的 5 处明暗差异规则。

主题开关的运行时配置

主题的明暗切换由设置系统驱动:packages/settings/src/types.ts 中ThemeSettings.colorScheme支持'light' | 'dark' | ''(''表示跟随系统),另有radius(圆角系数,0~1,默认 0.5)与colorAmblyopia(色弱模式)两个主题相关配置;默认值定义在 packages/settings/src/default.ts(colorScheme: 'light'、radius: 0.5、colorAmblyopia: false)。.dark类名的挂载与:root的切换,即由该配置联动uno.config.ts中的预置 CSS 生效。

七、小结

Fantastic-admin 的主题体系用"shadcn 标准 token + 框架专属--g-*token"两层结构,实现了组件语义色与布局区域色的解耦:shadcn token 以裸L C H数值定义语义,--g-*以oklch(var(--xxx))引用语义并分发到头部、主/次侧边栏、标签栏、工具栏等区域;明暗两套主题在菜单激活、主内容区背景、标签栏 hover/激活、菜单颜色引用 5 个维度上采用差异化取值策略。掌握 packages/themes/index.ts 中的变量结构,即可为 Fantastic-admin 创建符合规范、明暗自洽的全新主题。

  • 前端
  • AI 技能

【免费下载链接】basic

⭐⭐⭐⭐⭐ 面向 AI 编程的管理系统框架,兼容PC、移动端。AI-oriented management system framework, compatible with PC and mobile device.

项目地址:https://gitcode.com/GitHub_Trending/ba/basic
点击查看免费下载

相关推荐

上一篇:探索SOFA-PBRPC:百度开源的高性能RPC框架
下一篇:5步完成FastDepth模型训练:NYU Depth V2数据集实战指南

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询