CSS 颜色函数的取舍与兜底 · 色导网指南
新语法的收益主要在「从一个色派生另一个色」。但派生能力带来的维护风险也在这里,所以值得分清哪些该现在用、哪些该先写死。
各种写法的定位
| 写法 | 它擅长 | 建议 |
|---|---|---|
| #RRGGBB | 交付确定的色值 | 色板的真实来源用它,最稳 |
| rgb(R G B / A) | 需要 alpha 时 | 现代空格语法可读性更好,可以直接用 |
| hsl(H S% L%) | 手工微调同色相 | 别用它排色阶,L 不是感知亮度 |
| oklch(L C H) | 排等亮度色阶、做插值 | 值得用,但要给兜底 |
| color-mix() | 从一个色派生悬停态等 | 方便,但派生链过长会难以追溯 |
| 相对颜色语法 | 基于某色改一个分量 | 适合主题派生;同样需要兜底 |
兜底怎么写
CSS 的层叠本身就是兜底机制:先写旧语法,再写新语法。不认识新语法的浏览器会丢弃后一条声明,保留前一条。
.btn {
/* 旧浏览器拿到这一条 */
background: #2F5A91;
/* 认识 oklch 的浏览器用这一条 */
background: oklch(45% 0.09 250);
}用自定义属性时不能这样叠,因为变量的值在使用处才解析。这时用 @supports 整体覆盖一组变量更可靠:
:root {
--brand-500: #2F5A91;
--brand-600: #27497A;
}
@supports (color: oklch(50% 0.1 250)) {
:root {
--brand-500: oklch(45% 0.09 250);
--brand-600: oklch(38% 0.085 250);
}
}组织色板的两层变量
推荐分两层:第一层是原始色阶,命名只说颜色;第二层是语义变量,命名只说用途。组件只用第二层。
:root {
/* 第一层:色阶,不带用途 */
--blue-100: #E3EAF4;
--blue-500: #2F5A91;
--blue-700: #1F3A5F;
--gray-50: #FAF9F6;
--gray-700: #534F46;
/* 第二层:用途,组件只用这些 */
--bg-page: var(--gray-50);
--text-body: var(--gray-700);
--text-link: var(--blue-500);
--surface-accent: var(--blue-100);
}好处是换主题时只改第二层的指向,色阶本身不动;而且评审时能一眼看出哪个用途指到了哪一级——如果 --text-body 指到了 100 级,一看就知道不对。