主题系统最常见的失败方式,是把「结构」和「外观」搅在一起:某个组件为了改个圆角,顺手写死了 border-radius: 8px;某个页面为了调背景,直接写 background: #fff。

结果就是换主题要逐个组件去改。

分两层

结构刻度放 tokens.css:间距、圆角、动效时长与曲线。这些东西所有主题都一样。

语义色层放主题文件:--ui-bg、--ui-surface、--ui-text、--ui-accent……这些是「角色」,不是「颜色」。

组件只认角色:

.my-card {
  background: var(--ui-card-bg);
  border-radius: var(--ui-card-radius);
}

换主题时一个组件都不用动。

一条容易踩的规则

组件的 scoped 样式里不要再写 background / border-radius / box-shadow。

因为 scoped 选择器带着组件自己的属性,优先级比全局原语类高,会把主题盖掉。要调外观就走 variant / size,或者自己的 class 只调布局。

明暗模式是另一根轴

「浅色还是深色」和「长什么样」是正交的两件事。

明暗是运行时可切的(存 localStorage),主题是构建期定的。别把两者搅成一个变量。