最近产品经理希望在 B 端后台系统中增加品牌色功能,突显客户的企业特色。从技术上说,整个流程是非常简单的:
- 在配置中心为某个客户配置品牌色(十六进制颜色值)。
- 后台系统初始化时,通过后端接口读取配置的品牌色。
- 把品牌色写入为根元素的 CSS 变量。
核心流程代码如下:
const response = await fetch('/api/get-brand-info');
const data = await response.json();
document.documentElement.style.setProperty(
'--brand-primary-color',
data.primaryColor
);颜色替换
接下来要把项目中样式代码的颜色值改为 CSS 变量。颜色值的使用,一般有两种情况:
- 使用了 SCSS 等 CSS 扩展语言中的变量,所有颜色值都从变量取值;
- 直接用颜色值。
实际情况更有可能是这两种的混合——虽然使用了 SCSS 变量,但由于部分开发人员没有完全遵循规范,所以项目中既有颜色变量,也有颜色值。
$primary-color: #3F76FC;
.logo {
background: #3F76FC;
}
.selected {
color: $primary-color;
border: 1px solid $primary-color;
background: rgba($primary-color, 0.1);
}不过,不管是哪种情况,似乎都是把颜色值替换成 CSS 变量就可以了。以上述代码为例,即把「#3F76FC」替换为「var(--brand-primary-color, #3F76FC)」:
$primary-color: var(--brand-primary-color, #3F76FC);
.logo {
background: var(--brand-primary-color, #3F76FC);
}
.selected {
color: $primary-color;
border: 1px solid $primary-color;
background: rgba($primary-color, 0.1);
}替换后,马上发现问题——.selected 元素的背景色没了。通过浏览器开发工具可以发现,背景属性的值变成了:
background: rgba(var(--brand-primary-color, #3F76FC), 0.1);属于无效写法。造成这种情况,是因为「background: rgba($primary-color, 0.1)」中的「$primary-color」被编译成该变量的值了。
在 SCSS 中,可以用「rgba(#3F76FC, 0.1)」这种写法。编译过程中,编译器会把十六进制颜色值转成 RGB 颜色值,也就是编译成「rgba(63, 118, 252, 0.1)」。然而,把颜色值替换成 CSS 变量后,由于编译器也不知道颜色值是什么,所以无法进行转换。因此,这里必须用 RGB 颜色值。
对核心流程代码稍作修改,设置两个 CSS 变量,分别是 RGB 颜色值和十六进制颜色值:
import { hexToRGB } from '@polyv/utils/es/color';
const response = await fetch('/api/get-theme');
const data = await response.json();
document.documentElement.style.setProperty(
'--brand-primary-color-hex',
data.primaryColor
);
document.documentElement.style.setProperty(
'--brand-primary-color-rgb',
hexToRGB(data.primaryColor).join(',')
);接下来设置两个 SCSS 变量,分别是品牌色的十六进制表示和 RGB 表示:
$--primary-color-hex: var(--brand-primary-color-hex, #3F76FC);
$--primary-color-rgb: var(--brand-primary-color-rgb, 63, 118, 252);做两次替换操作:
- 把「rgba($--primary-color」以及「rgba(#3F76FC」替换为「rgba($--primary-color-rgb」。
- 把剩余的「$--primary-color」以及「#3F76FC」替换为「$--primary-color-hex」。
最终能正常运行的代码为:
$--primary-color-hex: var(--brand-primary-color-hex, #3F76FC);
$--primary-color-rgb: var(--brand-primary-color-rgb, 63, 118, 252);
.logo {
background: $--primary-color-hex;
}
.selected {
color: $--primary-color-hex;
border: 1px solid $--primary-color-hex;
background: rgba($--primary-color-rgb, 0.1);
}颜色计算
设计师希望后台系统左侧导航栏的底色是通过 25% 不透明度的品牌色叠加黑色得出。

虽说通过两个 HTML 元素叠加,就能做到这个效果,但是 HTML 结构和样式代码都会稍显复杂。通过 JavaScript 去计算出这个颜色值就方便多了:
export function mixWithBlack(color, opacity) {
const r = parseInt(hex.slice(0, 2), 16) * opacity;
const g = parseInt(hex.slice(2, 4), 16) * opacity;
const b = parseInt(hex.slice(4, 6), 16) * opacity;
const toHex = (c) => c.toString(16).padStart(2, '0');
return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
}
document.documentElement.style.setProperty(
'--brand-nav-bg-color',
mixWithBlack(data.primaryColor, 0.25)
);如果还有更复杂的颜色计算,也可以使用专业的第三方库,如 tinycolor。
最终效果

评论 (0条)