Skip to content

Theme Css

worable edited this page Oct 20, 2026 · 2 revisions

CSS Token 规范

theme.css 是主题的核心文件,通过 CSS 自定义属性(变量)定义视觉风格。

约束

StackPanel 主题的 CSS 不是通用 CSS,而是受限的 Token 声明。以下规则在上传时强制校验:

允许的内容

  • :root { } 块 — 亮色模式变量
  • .dark { } 块 — 暗色模式变量
  • 块内只能声明 --* 自定义属性

禁止的内容

禁止项 原因
url() 防止外部资源加载
@ 规则(@import、@media 等) 防止条件加载
选择器(除 :root 和 .dark) 主题是配置不是代码
expression() 防止表达式注入
</ 防止 HTML 注入
注释 /* */ 会被剥离,但不影响校验

示例

:root {
  --background: oklch(0.985 0.002 247);
  --foreground: oklch(0.21 0.006 247);
  --primary: oklch(0.6 0.12 250);
  --primary-foreground: oklch(0.985 0.002 247);
  --muted: oklch(0.955 0.005 247);
  --muted-foreground: oklch(0.5 0.008 247);
  --border: oklch(0.92 0.005 247);
  --success: oklch(0.62 0.08 155);
  --destructive: oklch(0.577 0.16 27.325);
  --radius: 0.625rem;
}

.dark {
  --background: oklch(0.17 0.006 250);
  --foreground: oklch(0.94 0.003 250);
  --primary: oklch(0.68 0.11 250);
  --primary-foreground: oklch(0.16 0.01 250);
  --muted: oklch(0.28 0.008 250);
  --muted-foreground: oklch(0.7 0.01 250);
  --border: oklch(1 0 0 / 10%);
}

变量名遵循 shadcn/ui 约定(--background、--foreground、--primary、--muted-foreground、--destructive 等),完整集合见内置 default 主题的 theme.css。

校验逻辑

validateThemeCss 的处理流程:

  1. 剥离注释 /* ... */
  2. 将 :root { ... } 和 .dark { ... } 块替换为空(如果块内内容合法)
  3. 将剩余内容压缩去空格
  4. 如果结果为空字符串 → 合法
  5. 如果包含 INVALID 或非空 → 非法

块内校验:每个声明必须匹配 ^--[a-zA-Z0-9_-]+\s*:,且不能包含 url(、@、expression(、</ 或反斜杠 \(防止 \75rl( 之类的转义绕过)。

大小限制

theme.css 最大 64 KB。

如何引用

前端通过 GET /themes/:id/theme.css 获取主题 CSS,由 ThemeStylesheet 以 <link rel="stylesheet"> 注入页面。Token 变量在 apps/web/src/app/globals.css 的 @theme inline 中映射为 Tailwind 语义类,组件用 bg-primary、text-muted-foreground 等类名消费;需要直接取值时用 var(--primary) 这类变量名,而非 var(--color-primary)。

暗色模式

亮色变量写在 :root,暗色变量写在 .dark。前端由 next-themes 按 attribute="class"、defaultTheme="system" 在 <html> 上切换 dark 类,.dark 块中的同名变量随之覆盖 :root。supportsDarkMode 目前只是清单能力标记,不参与切换逻辑。

Clone this wiki locally