less不支持contrast()函数,需用luma公式结合if()判断文字色:@luma: 0.2126@r + 0.7152@g + 0.0722*@b;若@luma>0.5则用深色字,否则用浅色字。

Less里没有内置contrast()函数,别直接写
Less本身不提供类似Sass的contrast()或CSS color-contrast()(后者尚未广泛支持)这种自动计算文字色的函数。你如果在Less文件里直接写contrast(@bg, black, white),编译会报错:Unrecognised input。Less的内置颜色函数只有lighten()、darken()、spin()、mix()等,不带感知亮度的智能对比逻辑。
用luma() + 条件判断模拟对比色
可靠做法是手动计算背景色的相对亮度(luma),再按阈值决定文字色。W3C推荐的luma公式是:0.2126 * R + 0.7152 * G + 0.0722 * B(归一化后)。Less虽不能运行JS,但可通过嵌套函数+if()(需Less 4.0+)组合实现:
.text-auto {
@bg: #2a5c82;
@r: red(@bg) / 255;
@g: green(@bg) / 255;
@b: blue(@bg) / 255;
@luma: (0.2126 * @r) + (0.7152 * @g) + (0.0722 * @b);
color: if(@luma > 0.5, #333, #fff);
}
- 注意
red()/green()/blue()返回的是0–255整数,必须除以255转为0–1区间才能代入luma公式 - 阈值0.5是常用分界点,偏保守;深灰背景(如
#333)luma≈0.21,此时会选#fff;浅灰(#ccc)luma≈0.76,选#333 - 该方法对纯色和
rgb()/hex有效,但不支持hsl()输入——得先转rgb(),Less无内置转换,建议预处理
遇到渐变或半透明背景时,luma()会失效
如果@bg是linear-gradient()或带alpha的rgba(0,0,0,0.5),red()等函数无法解析,编译直接失败。此时不能依赖Less计算,必须换策略:
- 把文字色决策上提到CSS变量层:用JS读取真实渲染后的
getComputedStyle,算luma后动态设--text-color - 或约定设计规范:所有半透明背景只搭配固定文字色(如
rgba(255,255,255,0.9)),绕过自动逻辑 - Less里可加注释警告:
// ⚠️ @bg must be solid hex/rgb — no gradients or alpha
实际项目中更推荐抽成参数化mixin
重复写luma逻辑易出错,封装成mixin复用更安全:
.auto-color(@bg) when (iscolor(@bg)) {
@r: red(@bg) / 255;
@g: green(@bg) / 255;
@b: blue(@bg) / 255;
@luma: (0.2126 * @r) + (0.7152 * @g) + (0.0722 * @b);
color: if(@luma > 0.52, #222, #f8f9fa);
}
// 使用
.card { .auto-color(#1e3a5f); }
这个mixin加了when (iscolor(@bg))守卫,避免传入非颜色值导致编译崩溃;阈值微调到0.52是为了让#4a6fa5这类蓝调色也倾向白字——人眼对蓝色敏感度低,纯0.5有时不够保险。
真正难的不是算公式,而是得想清楚:这个“自动”到底要覆盖哪些背景类型、能否接受近似结果、设计师是否认可阈值逻辑。一旦背景来自主题配置或CMS动态注入,Less编译期就无能为力了。










