乐趣区

关于前端:CSS-如何根据背景色自动切换黑白文字

欢送关注我的公众号:前端侦探

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

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

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

这样能够失去一个 0~1 之间的范畴值,能够依据需要,设定一个阈值,超过示意为浅色,否则为深色。

原理就是这样,这里就不多介绍了。

那么,纯 CSS 也能实现这样的成果吗?当然能够,而且实现更简略,一起看看吧

一、CSS 滤镜实现

实现这个成果须要用到 CSS 滤镜。

假如有 HTML 是这样的

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

因为要应用滤镜对文字独自解决,所以须要额定一层标签。

而后,容器和文字用同一种色彩示意,目标是 让文字色彩和背景相关联 ,能够通过currentColor 实现

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

接下来能够想一下,如何让黑白文字变成黑白

提到黑白,能够想到灰度滤镜(grayscale),置信大家前几天都用到过,这样能够将黑白的文字转换成灰色

.text{filter: grayscale(1)
}

成果如下

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

然而,这种灰色在当初这种背景下太难看清 了,咱们须要的是纯正的彩色或者红色,当初只是灰色,如何“增强”一下呢?

这时,咱们能够用到对比度滤镜(contrast),在后面的根底上再叠加一层

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

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

这样能还不太显著,咱们把背景色换一下

最初,还差一步,因为后面的操作是将原有色彩通过滤镜转换成了和本身绝对应的红色或者彩色,然而是相同的,所以须要用到反转滤镜(invert),颠倒是非

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

成果如下

上面用一张图来示意转换过程

上面是任意色彩的适配成果,还是挺完满的

代码很简略,就这么一行

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

残缺代码能够查看以下任意链接

  • CSS auto-color (codepen.io)

二、CSS 其余思路

除了下面这种形式,还能够通过 CSS 变量来实现,要简单一些。

这里简略介绍一下实现思路

  1. 将色彩 RGB 值拆分成 3 个独立的 CSS 变量
  2. 通过灰度算法,用 CSS 计算函数算出灰度
  3. 用失去的灰度和阈值做差值,通过 hsl 模式转换成纯黑和纯白

有趣味的能够参考张鑫旭老师的这篇文章:CSS 前景背景主动配色技术简介,能够看到,整体实现和 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%));
}

成果如下

相比后面的实现而言,实现更加灵便,能够少一层标签。

另外,CSS 正在起草一个色彩比照函数color-contrast,能够从几个色彩中主动抉择对比度最高的那个,实现是这样的

.text-contrast-primary {color: color-contrast(var(--theme-primary) vs white, black);
}

不过,当初还没有任何浏览器反对。

如果未来反对了,这将是终极解决方案。

三、优缺点总结

总的来说,在 color-contrast 函数反对之前,我更举荐 CSS 滤镜形式,有以下几点益处

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

当然,也是存在一些毛病

  1. 须要独自一层标签,应用场景可能有限度
  2. 对色彩敏感度较高,不然无从下手
  3. 色彩转换有限度,最终只能是黑白,其余色彩就无能为力了

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

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

从新领会色彩转换过程

你记住了吗?最初,如果感觉还不错,对你有帮忙的话,欢送 点赞、珍藏、转发❤❤❤

欢送关注我的公众号:前端侦探

退出移动版