主题系统最常见的失败方式,是把「结构」和「外观」搅在一起:某个组件为了改个圆角,顺手写死了 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),主题是构建期定的。别把两者搅成一个变量。