在項目中,經常會碰到背景色不確定的場景,為了讓內容文字足夠清晰可見,文字和背景之間需要有足夠的對比度。換句話說,當背景是深色時,文字為白色,當背景是淺色時,文字為黑色,就像這樣:

通常這種情況,大家可能會通過 js 去計算背景色的深淺度(灰度),算法是公開的,如果已知顏色的RGB值,那麼可以通過以下方式得到顏色灰度
luma=(red*0.2126+green*0.7152+blue*0.0722)/255這樣可以得到一個0~1之間的範圍值,可以根據需求,設定一個閾值,超過表示為淺色,否則為深色。
原理就是這樣,這裡就不多介紹了。
那麼,純 CSS 也能實現這樣的效果嗎?當然可以,而且實現更簡單,一起看看吧
一、CSS 濾鏡實現實現這個效果需要用到 CSS 濾鏡。
假設有 HTML 是這樣的
<divclass="box"><spanclass="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 變量來實現,要複雜一些。
這裡簡單介紹一下實現思路
有興趣的可以參考張鑫旭老師的這篇文章: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));/***使用sRGBLuma方法計算灰度(可以看成亮度)*算法為:*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)vswhite,black);}不過,現在還沒有任何瀏覽器支持。

如果將來支持了,這將是終極解決方案。
三、優缺點總結總的來說,在color-contrast函數支持之前,我更推薦 CSS 濾鏡方式,有以下幾點好處
當然,也是存在一些缺點
下面來回顧一下用到的3個濾鏡,總結一下
重新體會顏色轉換過程

好了,本文到此結束,希望對你有所幫助。
參考資料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/
