色导网中文配色工作台与色彩资料馆

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 级,一看就知道不对。