歡迎關注我的公眾號:前端偵探
在上一篇 CSS 如何根據背景色自動切換黑白文字?中,講述了文字自適應背景色的一些小技巧,不過還存在一定侷限性,比如:如果是背景是漸變色該怎麼辦?
很容易想到的思路是將兩個漸變色取過渡中間色,然後再透過前面的方式轉換就行了
那麼問題來了,有沒有辦法透過 CSS 實現中間顏色的獲取呢?今天來一起探討這個問題,聊一聊關於顏色合成的相關技巧。
一、你可能不知道 CSS 動畫小技巧
想必大家都用過 CSS 動畫,比如
@keyframes color {
from {
color: yellow
}
to{
color: deeppink
}
}
.text{
animation: color 1s linear forwards;
}
這樣就得到了一個顏色從yellow
到deeppink
的動畫
這個沒什麼好說的。
預設情況下,動畫會播放 1 次後結束,然後設定了forwards
,會保留在最後一幀狀態。
那麼,如果動畫只播放一半,是不是就正好處於兩者顏色的中間?其實,播放次數也可以是小數的,比如可以將播放次數設定為0.5
次,就像這樣
.text{
animation: color 1s .5 linear forwards;
}
效果如下
由於只播放了一半,所以到中間的橙色就停止了下來。
值得一提的是,透過這種方式得到的顏色,也是可以用 JS 去獲取的
那麼,利用這個特性,可以實現顏色的各種合成效果。
二、漸變背景下的文字自適應
回到前面的問題,如果是漸變背景,該如何實現自動切換黑白文字呢?
假設漸變的兩種顏色分別是--c1
和--c2
,
<div class="box" style="--c1: #ffeb3b; --c2: deeppink">
<span class="txt">前端偵探</span>
</div>
那麼根據上一節的方法,可以將動畫改造成這樣
@keyframes color {
from {
color: var(--c1)
}
to{
color: var(--c2)
}
}
我們這裡只是需要獲取一下顏色,並不需要動畫,所以可以將動畫時長設定為很小的一個數,比如0.001s
.txt{
animation: color .001s .5 linear forwards;
}
這樣文字顏色就自動變成了漸變顏色的中間值,如下
然後再應用濾鏡,將文字轉換成黑色或者白色
.txt{
animation: color .001s .5 linear forwards;
filter: grayscale(1) contrast(9999) invert(1);
}
效果如下
也能完美適配任意漸變色
完整程式碼可以檢視以下任意連結
三、顏色的加深和減淡
再來看一個更加實用的例子,顏色的加深和減淡。通常用於主題色的生成,比如給定一個主題色,生成一系列和它相匹配的鄰近色。下面是顏色逐漸減淡,最終變為白色的色階圖
根據上面的原理,可以很輕易的實現這樣一個效果
假設 HTML 是這樣的,每個方塊給一個不同的 CSS 變數--l
<div class="box" style="--l:0"></div>
<div class="box" style="--l:0.2"></div>
<div class="box" style="--l:0.4"></div>
<div class="box" style="--l:0.6"></div>
<div class="box" style="--l:0.8"></div>
<div class="box" style="--l:1"></div>
然後建立一個從主題色到白色的動畫,根據這個變數,讓動畫執行不同的次數
.box{
animation: lighterBackgroundColor .001s var(--l) linear forwards;
}
@keyframes lighterBackgroundColor {
from {
background-color: var(--primary-color)
}
to{
background-color: #fff
}
}
這樣就可以生成同種顏色,不同深淺度的主題色了
有同學可能會說像 sass
、less
這些不也能實現嗎?其實不然,這些都是前處理器,生成以後就不能再變了,而這種方式是實時繪製的,可以實現修改,如下
完整程式碼可以檢視以下任意連結
如果將這種技巧用到實際專案中也是非常完美,下面是不同主題色下的預覽效果
選中背景色就是減淡80%
後的顏色
.item.current{
border-color: var(--primary-color);
animation: lighterBackgroundColor .001s .8 linear forwards;
}
原理是完全相同的,這裡就不詳細介紹了,完整程式碼可以檢視以下任意連結
除此之外,根據需求,還可以透過顏色透明度的變化來生成特定透明度的主題色
@keyframes OpacityBackgroundColor {
from {
background-color: var(--primary-color)
}
to{
background-color: rgba(0,0,0,0)
}
}
四、未來最期待的幾個顏色處理函式
官方也看到了這種需求,因此在 CSS Color Module Level 5中起草了幾個關於顏色合成的函式,這裡簡單介紹一下
首先是顏色混合color-mix
,將兩種顏色按照一定的比例進行融合
color-mix(in srgb, white, blue);
這表示white
和blue
按照各自 50%
進行混合,最終會得到紫色rgb(50% 50% 100%)
如果要控制混合比例,可以這樣
color-mix(in srgb, white 20%, blue);
還有一個叫做相對顏色relative color
,其實是對原有的顏色函式進行了補充,根據我的理解,可以將這個特性想象成 JS 中的解構賦值
hsl(from var(--accent) h s calc(l - 20%))
例如這個表示將顏色--accent
分解成h
、s
、l
三個變數,然後對其中的l
,也就是亮度減少20%
,也就達到了顏色變暗的目的
多麼令人興奮的特性!目前這兩個特性僅在 safari 15+
試驗性功能開啟支援(?終於不拖後腿了)
五、總結一下
以上就是本文全部內容了,主要是利用 CSS 動畫的過渡特性,間接達到了顏色混合的目的,下面是一些要點:
- CSS 動畫的次數也能設定成小數,比如 0.5 表示動畫只執行到一半
- 兩個顏色的中間色就是顏色動畫執行到一半的狀態
- 顏色減淡可以看成是主題色到白色的動畫,加深則是黑色
- 官方已經正在起草 CSS 顏色合成相關函式,目前僅 Safari 試驗性支援
你學會了嗎?總的來說,在color-mix
到來之前,這樣一個小技巧還算是不錯的解決方案。最後,如果覺得還不錯,對你有幫助的話,歡迎點贊、收藏、轉發❤❤❤
歡迎關注我的公眾號:前端偵探