luma()函数基于sRGB加权计算颜色相对亮度(0.2126r+0.7152g+0.0722b),用于判断文字可读性;需传入明确颜色值,深色背景(<0.5)配白字、浅色(≥0.5)配黑字,可用if()和.text-contrast() mixin封装实现自动反色。

Less里用luma()计算背景亮度值
Less内置的luma()函数返回颜色的相对亮度(0–1之间的数值),它基于sRGB通道加权计算:luma = 0.2126 * r + 0.7152 * g + 0.0722 * b。这个值比简单取平均或灰度更符合人眼感知,是判断文字可读性的可靠依据。
注意:luma()只接受颜色值(如#333、rgb(51, 51, 51)、hsl(0, 0%, 20%)),不支持变量未求值前的表达式——比如luma(@bg-color)要求@bg-color必须是明确颜色,不能是字符串或未定义变量。
- 深色背景(
luma < 0.5)通常配白色文字 - 浅色背景(
luma >= 0.5)配黑色文字更安全 - 临界值0.5不是绝对阈值,可根据设计规范微调(如0.45或0.55)
用if()做条件分支选文字色
Less的if()是三元运算函数:if(condition, true-value, false-value)。它不能执行语句,只能返回一个值,所以适合直接赋给color属性。
典型写法:
立即学习“前端免费学习笔记(深入)”;
button {
background-color: @bg;
color: if(luma(@bg) >= 0.5, #000, #fff);
}常见错误:
- 把
if()写成if (luma(...) >= 0.5) { ... }——Less不支持这种块级语法 - 在
if()里混用单位或非颜色值,比如if(..., 14px, 16px)——类型必须一致,这里只适用于颜色 - 对透明色(
rgba(0,0,0,0))调用luma()会报错,需提前过滤或默认 fallback
封装成可复用的.text-contrast()混合宏
避免每个地方重复写if(luma(...)),建议抽成参数化混合(mixin):
.text-contrast(@bg; @light: #000; @dark: #fff; @threshold: 0.5) {
color: if(luma(@bg) >= @threshold, @light, @dark);
}使用时只需传入背景色:
.card-primary {
background-color: #007bff;
.text-contrast(#007bff);
}
.card-light {
background-color: #f8f9fa;
.text-contrast(#f8f9fa; @light: #333; @dark: #fff);
}关键点:
-
@light和@dark参数支持自定义,适配品牌色系统(比如深灰#212529替代纯黑) - 不要在 mixin 内部用
@bg做二次计算(如lighten(@bg, 10%))再传给luma()——luma()只认原始输入色 - 若
@bg是 CSS 变量(--bg-color),Less 无法编译期读取,此方案不适用
遇到渐变背景或图片时怎么办
luma()只支持单色,对linear-gradient()或url()背景直接报错。此时自动逻辑失效,必须人工干预:
- 渐变背景:取主色(如起始色)估算,或改用固定高对比文字色(如始终用
#fff并加文字阴影增强可读性) - 图片背景:无法静态分析,应配合
background-blend-mode或半透明白/黑遮罩层,再设固定文字色 - 组件库中建议将“自动反色”作为可选模式,并提供
data-contrast="light"等标记供手动覆盖
真正难的不是写对luma(),而是意识到它只解决单色场景——一旦背景脱离纯色范畴,就得退回到设计约定和视觉校验。


















