您可能知道,最近对CSS的更新和添加非常强大。从Flexbox到Grid,以及 – 我们在这里关注的 – 自定义属性(也就是 CSS变量),所有这些都使得强大的动态布局和界面比以往更容易,同时打开了我们过去梦寐以求的许多其他可能性。
前几天,我认为必须有一种方法可以使用自定义属性为元素的背景着色,同时保持与足够高的前景色(使用白色或黑色)的对比度,以通过WCAG AA可访问性标准。
使用几行代码在JavaScript中执行此操作非常有效:
var rgb = [255, 0, 0];
function setForegroundColor() {
var sum = Math.round(((parseInt(rgb[0]) * 299) + (parseInt(rgb[1]) * 587) + (parseInt(rgb[2]) * 114)) / 1000);
return (sum > 128) ? 'black' : 'white';
}
这将获取元素背景颜色的红色,绿色和蓝色(RGB)值,将它们乘以一些特殊数字(分别为299,587和144),将它们相加,然后将总数除以1,000。当该总和大于128时,它将返回黑色; 否则,我们会变白。还不错。
唯一的问题是,当在CSS中重新创建它时,我们无法访问本机if
语句来评估总和。那么,如何在没有CSS的情况下在CSS中复制它?
幸运的是,像HTML一样,CSS可以非常宽容。如果我们将一个大于255的值传递给RGB函数,它将被限制在255.对于低于0的数字也是如此。即使负整数也会被限制为0.因此,不测试我们的总和是大于还是小于128,我们从总和中减去128,给出正整数或负整数。然后,如果我们将它乘以一个大的负值(例如-1,000),我们最终得到非常大的正值或负值,然后我们可以传递给RGB函数。就像我之前说的那样,这将受限于浏览器的期望值。
以下是使用CSS变量的示例:
:root {
–red: 28;
–green: 150;
–blue: 130;
–accessible-color: calc(
(
(
(var(–red) * 299) +
(var(–green) * 587) +
(var(–blue) * 114) /
1000
) – 128
) * -1000
);
}
.button {
color:
rgb(
var(–accessible-color),
var(–accessible-color),
var(–accessible-color)
);
background-color:
rgb(
var(–red),
var(–green),
var(–blue)
);
}
如果我的数学是正确的(并且它很可能不是),我们总共得到16,758,远远超过255.将此总数传递rgb()
给所有三个值的函数,浏览器将文本颜色设置为白色。
在这一点上,一切似乎都在Chrome和Firefox中运行,但Safari有点胡思乱想并给出了不同的结果。起初,我认为这可能是因为Safari没有限制我在函数中提供的大值,但经过一些测试后,我发现Safari出于某种原因不喜欢我计算中的除法。
仔细看看这个calc()
函数,我注意到我可以通过增加128到128,000的值来删除1,000的除法。到目前为止,这是看起来如何:
:root {
–red: 28;
–green: 150;
–blue: 130;
–accessible-color: calc(
(
(
(var(–red) * 299) +
(var(–green) * 587) +
(var(–blue) * 114)
) – 128000 /* HIGHLIGHT */
) * -1000
);
}
.button {
color:
rgb(
var(–accessible-color),
var(–accessible-color),
var(–accessible-color)
);
background-color:
rgb(
var(–red),
var(–green),
var(–blue)
);
}
扔几个范围的滑块来调整color
值,你就拥有它:一个动态的UI元素,它可以根据它交换文本颜色,background-color
同时保持WCAG AA的通过等级。
将这个概念付诸实践
下面是一个笔,显示了如何使用此技术来主题用户界面。我已经复制并将--accessible-color
变量移动到需要它的特定CSS规则中,并且为了帮助确保背景可以根据它们的前景保持可访问,我--accessible-color
在几个地方将变量乘以-1。可以使用位于右下角的控件更改颜色。单击齿轮/齿轮图标以访问它们。
还有其他方法可以做到这一点
不久前,Facundo Corradini 在这篇文章中解释了如何做一些非常相似的事情。他使用略微不同的计算结合hsl
函数。他还详细介绍了他在提出这个概念时遇到的一些问题:
有些色调确实存在问题(特别是黄色和青色),因为尽管具有相同的亮度值,但它们显示的方式比其他色调更明亮(例如红色和蓝色)。因此,尽管非常明亮,但某些颜色被视为暗色和白色文本。
CSS的名称是什么?
他继续提到Edge并没有限制他的大数字,在我的测试中,我注意到有时候它正在工作,有时则不然。如果有人能够找到原因,可以随意分享评论。
此外,Ana Tudor解释了如何使用filter
+ mix-blend-mode
可以帮助将文本与更复杂的背景进行对比。而且,当我说复杂时,我的意思是复杂的。她甚至可以证明文本颜色如何随着背景颜色的变化而变化 – 非常棒!
此外,Robin Rendle解释了如何mix-blend-mode
与伪元素一起使用以根据文本颜色自动反转文本颜色background-color
。
因此,将此视为另一种投入混合的方法。Custom Properties为我们开辟了这些可能性,同时允许我们以各种方式解决同样的问题,这真是太棒了。