不引入构建步骤的设计令牌实践
手头几个站点形态相近、又不想为样式引入构建链路。记录用 CSS 自定义属性和级联层做出一套够用的设计系统,以及命名上踩过的坑。
起因是想统一几个子站的视觉。能选的路线有两条:引入一套现成的组件库,或者自己抽一层样式基础。前者要接构建工具、要跟着上游升级,对几个流量不大的站点来说太重了;我选了后者。
把令牌单独一层
第一件事是把"值"和"用法"分开。颜色、间距、圆角、阴影、字阶这些原始值只在一个地方定义,其余所有样式只引用变量名,不出现字面量。这样换一整套配色的时候,改动被限制在令牌文件里。
:root {
/* 令牌层:只在这里出现字面值 */
--accent: #0e7490;
--surface: #ffffff;
--border: #e7e7e4;
--radius-card: 14px;
--space-4: 16px;
/* 语义层:组件只引用这一层 */
--card-bg: var(--surface);
--card-border: 1px solid var(--border);
}深色模式也落在这一层:媒体查询里只覆盖令牌,不动任何组件样式。组件不需要知道自己是深色还是浅色。
级联层解决顺序问题
没有构建步骤的时候,样式表的加载顺序决定优先级,很容易出现"某个页面的样式被后加载的通用样式覆盖"。CSS 的 @layer 可以把优先级从"加载顺序"变成"显式声明的层序",通用样式即使在后面加载也不会压过页面样式。目前主流浏览器已经支持,是可以放心用的。
@layer tokens, base, components, pages;
@layer components { /* 通用组件 */ }
@layer pages { /* 页面特有样式,优先级更高 */ }命名上的教训
一开始组件类名直接用语义名,很快就跟已有站点的类名撞了。后来统一加了一个短前缀,并且约定"前缀只留给这层设计系统,页面自有样式不占用",冲突就消失了。命名上的这点约束,比任何工具都管用。