在项目中,经常会碰到背景色不确定的场景,为了让内容文字足够清晰可见,文字和背景之间需要有足够的对比度。换句话说,当背景是深色时,文字为白色,当背景是浅色时,文字为黑色,就像这样:
image-20221226102604970
通常这种情况,大家可能会通过 js 去计算背景色的深浅度(灰度),算法是公开的,如果已知颜色的RGB
值,那么可以通过以下方式得到颜色灰度
luma = (red * 0.2126 + green * 0.7152 + blue * 0.0722) / 255
这样可以得到一个0~1
之间的范围值,可以根据需求,设定一个阈值,超过表示为浅色,否则为深色。
原理就是这样,这里就不多介绍了。
那么,纯 CSS 也能实现这样的效果吗?当然可以,而且实现更简单,一起看看吧
实现这个效果需要用到 CSS 滤镜。
假设有 HTML
是这样的
<div class="box">
<span class="txt">前端侦探</span>
</div>
因为要使用滤镜对文字单独处理,所以需要额外一层标签。
然后,容器和文字用同一种颜色表示,目的是让文字颜色和背景相关联,可以通过currentColor
实现
.box{
color: #ffeb3b;
background-color: currentColor;
}
接下来可以想一下,如何让彩色文字变成黑白?
提到黑白,可以想到灰度滤镜(grayscale
),相信大家前几天都用到过,这样可以将彩色的文字转换成灰色
.text{
filter: grayscale(1)
}
效果如下
image-20221224165239122
这样文字颜色由原来的黄绿色变成了浅灰色。
但是,这种灰色在现在这种背景下太难看清了,我们需要的是纯正的黑色或者白色,现在只是灰色,如何“加强”一下呢?
这时,我们可以用到对比度滤镜(contrast
),在前面的基础上再叠加一层
.text{
filter: grayscale(1) contrast(999)
}
这里的对比度给的比较大,这样就会极大的增强对比度,黑的更黑,白的更白,如果是浅灰,那就变成白色,如果是深灰,那就变成黑色,效果如下
image-20221224165207221
这样能还不太明显,我们把背景色换一下
image-20221224155024179
最后,还差一步,由于前面的操作是将原有颜色经过滤镜转换成了和自身相对应的白色或者黑色,但是是相反的,所以需要用到反转滤镜(invert
),颠倒黑白
.text{
filter: grayscale(1) contrast(999) invert(1)
}
效果如下
image-20221224155446675
下面用一张图来表示转换过程
image-20221224165935410
下面是任意颜色的适配效果,还是挺完美的
Kapture 2022-12-23 at 14.43.29
代码很简单,就这么一行
.text{
filter: grayscale(1) contrast(999) invert(1)
}
完整代码可以查看以下任意链接
除了上面这种方式,还可以通过 CSS 变量来实现,要复杂一些。
这里简单介绍一下实现思路
RGB
值拆分成 3 个独立的 CSS变量hsl
模式转换成纯黑和纯白有兴趣的可以参考张鑫旭老师的这篇文章:CSS前景背景自动配色技术简介[4],可以看到,整体实现和 js 逻辑几乎是一致的,下面是完整实现
另外可以参考之前这篇文章:[CSS 变量自动变色技术]
:root {
/* 定义RGB变量 */
--red: 44;
--green: 135;
--blue: 255;
/* 文字颜色变色的临界值,建议0.5~0.6 */
--threshold: 0.5;
}
.btn {
/* 按钮背景色就是基本背景色 */
background: rgb(var(--red), var(--green), var(--blue));
/**
* 使用sRGB Luma方法计算灰度(可以看成亮度)
* 算法为:
* lightness = (red * 0.2126 + green * 0.7152 + blue * 0.0722) / 255
*/
--r: calc(var(--red) * 0.2126);
--g: calc(var(--green) * 0.7152);
--b: calc(var(--blue) * 0.0722);
--sum: calc(var(--r) + var(--g) + var(--b));
--lightness: calc(var(--sum) / 255);
/* 设置颜色 */
color: hsl(0, 0%, calc((var(--lightness) - var(--threshold)) * -999999%));
}
效果如下
auto-color-button.gif (228×225) (zhangxinxu.com)
相比前面的实现而言,实现更加灵活,可以少一层标签。
另外,CSS 正在起草一个颜色对比函数color-contrast
,可以从几个颜色中自动选择对比度最高的那个,实现是这样的
.text-contrast-primary {
color: color-contrast(var(--theme-primary) vs white, black);
}
不过,现在还没有任何浏览器支持。
image-20221224174008923
如果将来支持了,这将是终极解决方案。
总的来说,在color-contrast
函数支持之前,我更推荐 CSS 滤镜方式,有以下几点好处
RGB
模式当然,也是存在一些缺点
下面来回顾一下用到的3个滤镜,总结一下
grayscale
),可以将彩色的文字转换成灰色contrast
),可以极大的增强对比度,黑的更黑,白的更白,如果是浅灰,那就变成白色,如果是深灰,那就变成黑色invert
),可以翻转颜色,颠倒黑白重新体会颜色转换过程
image-20221224165935410
[1]CSS auto-color (juejin.cn): https://code.juejin.cn/pen/7180639403566448698
[2]CSS auto-color (codepen.io): https://codepen.io/xboxyan/pen/bGjVbGj
[3]CSS auto-color (runjs.work): https://runjs.work/projects/bb844abe80da401d
[4]CSS前景背景自动配色技术简介: https://www.zhangxinxu.com/wordpress/2018/11/css-background-color-font-auto-match/
Copyright© 2013-2020
All Rights Reserved 京ICP备2023019179号-8