Skip to content

CSS 如何根据背景色自动切换黑白文字?

在项目中,经常会碰到背景色不确定的场景,为了让内容文字足够清晰可见,文字和背景之间需要有足够的对比度。换句话说,当背景是深色时,文字为白色,当背景是浅色时,文字为黑色,就像这样:

通常这种情况,大家可能会通过 js 去计算背景色的深浅度(灰度),算法是公开的,如果已知颜色的 RGB 值,那么可以通过以下方式得到颜色灰度

js
luma = (red * 0.2126 + green * 0.7152 + blue * 0.0722) / 255

这样可以得到一个 0~1 之间的范围值,可以根据需求,设定一个阈值,超过表示为浅色,否则为深色。

那么,纯 CSS 也能实现这样的效果吗?当然可以,而且实现更简单,一起看看吧。

CSS 滤镜实现

实现这个效果需要用到 CSS 滤镜。

假设有 HTML 是这样的:

html
<div class="box">
  <span class="txt">前端侦探</span>
</div>

因为要使用滤镜对文字单独处理,所以需要额外一层标签 <span class="txt">

然后,容器和文字用同一种颜色表示,目的是让文字颜色和背景相关联,可以通过 currentColor 实现:

css
.box{
  color: #ffeb3b;
  background-color: currentColor;
}

如何让彩色文字变成黑白?

提到黑白,可以想到灰度滤镜(grayscale),这样可以将彩色的文字转换成灰色。

css
.text{
  filter: grayscale(1)
}

效果如下

这样文字颜色由原来的黄绿色变成了浅灰色。

但是,这种灰色在现在这种背景下太难看清了,我们需要的是纯正的黑色或者白色,现在只是灰色,如何“加强”一下呢?

这时,我们可以用到对比度滤镜(contrast),在前面的基础上再叠加一层

css
.text{
  filter: grayscale(1) contrast(999)
}

这里的对比度给的比较大,这样就会极大的增强对比度,黑的更黑,白的更白,如果是浅灰,那就变成白色,如果是深灰,那就变成黑色,效果如下

最后,还差一步,由于前面的操作是将原有颜色经过滤镜转换成了和自身相对应的白色或者黑色,但是是相反的,所以需要用到反转滤镜(invert),颠倒黑白

css
.text{
  filter: grayscale(1) contrast(999) invert(1)
}

效果如下

下面用一张图来表示转换过程

下面是任意颜色的适配效果,还是挺完美的

代码很简单,就这么一行(但要注意使用条件,需要多套一层标签)。

css
.text{
  filter: grayscale(1) contrast(999) invert(1)
}

优缺点总结

CSS 滤镜方式,有以下几点好处:

  1. 代码简洁,就一行代码,3 个滤镜
  2. 对颜色格式无任何要求,无需转换成 RGB 模式
  3. 无需了解颜色算法,对设计更为友好

当然,也是存在一些缺点:

  1. 需要单独一层标签,使用场景可能有限制
  2. 颜色转换有限制,最终只能是黑白,其他颜色就无能为力了

下面来回顾一下用到的 3 个滤镜,总结一下

  1. 灰度滤镜(grayscale),可以将彩色的文字转换成灰色
  2. 对比度滤镜(contrast),可以极大的增强对比度,黑的更黑,白的更白,如果是浅灰,那就变成白色,如果是深灰,那就变成黑色
  3. 反转滤镜(invert),可以翻转颜色,颠倒黑白

Released under the MIT License.