contrast() 函数不能保障 wcag 对比度,仅按亮度阈值返回黑白;需手动实现 luma() 计算并设阈值 0.55;渐变/透明背景须用主色变量驱动;输出必须为静态 hex 或 rgb() 值;小字号文本需人工校验渲染后对比度。

contrast() 函数在 Less 中不能直接用于无障碍对比度保障——它只返回黑或白,不校验 WCAG 4.5:1 是否达标。
Less 的 contrast() 是一个亮度阈值判断函数,不是对比度计算函数。它内部只算相对亮度(luma),然后按固定阈值(默认 0.43)决定返回 #000 还是 #fff。哪怕背景是 #2c3e50(luma ≈ 0.22),它仍返回 #fff,但该组合实测对比度仅约 6.2:1;而换成更暗的 #1a252f,对比度就掉到 3.8:1,contrast() 却依然返回白——已不满足 AA 级要求。
用 luma() 手动建模才是可靠路径
-
luma()不是 Less 内置函数,需手动定义:基于 sRGB 加权公式(0.2126 <em> R + 0.7152 </em> G + 0.0722 * B) / 255 - 必须先用
rgb(@color)转格式,再用red()/green()/blue()提取通道值 -
unit(..., '')去除单位(如255px→255),否则运算会失败 - 阈值建议设为
0.55而非0.5:中灰#808080的 luma 正好是 0.5,但人眼在此区间对黑白都易疲劳,略偏亮侧更可读
示例 mixin:
.text-color-for-bg(@bg) {
@rgb: rgb(@bg);
@r: unit(red(@rgb), '');
@g: unit(green(@rgb), '');
@b: unit(blue(@rgb), '');
@luma: (0.2126 * @r + 0.7152 * @g + 0.0722 * @b) / 255;
color: if(@luma > 0.55, #000, #fff);
}
渐变、透明背景无法套用自动逻辑
-
linear-gradient()或rgba(0,0,0,0.3)无法被red()解析,Less 会报错或返回0 - 不是函数写得不对,而是问题类型变了:CSS 渐变没有单一“背景色”,算法无输入源
- 正确做法是把“主色”抽成变量(如
@card-bg-base: #4a6fa5),用它驱动.text-color-for-bg(),渐变/透明效果用伪元素或覆盖层单独实现
输出必须是静态 hex 或 rgb() 值
- WebAIM Contrast Checker、axe、Lighthouse 等工具只识别编译后确定的
#000、rgb(0, 0, 0),拒绝rgba()、currentColor、变量插值(如~"rgb(@{r}, @{g}, @{b})") - Mixin 内禁止用
@{var}拼接颜色字符串,编译器不保证类型安全,可能产出非法值 - 所有条件分支(
if())必须直接返回硬编码值,确保开发者工具“Computed”面板看到的是纯rgb(),而非计算过程残留
真正容易被忽略的是小字号文本的渲染衰减——14px 文字加抗锯齿后边缘灰度上升,有效对比度可能比理论值低 0.3–0.5:1。此时靠 luma > 0.55 判断远远不够,必须人工用工具在校验色块上叠加实际字体渲染效果再确认。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











