(給前端大學加星標,提升前端技能.)
作者:張鑫旭
https://www.zhangxinxu.com/wordpress/2020/07/css-background-blend-mode/
一、可能都知道的首先,講兩點大家可能都知道的知識點:
background-blend-mode本身就帶有隔離特性,也就是一個元素應用background-blend-mode背景混合模式,最終的效果只會受當前元素的背景圖像和背景顏色影響,不會受視覺上處於當前區域其他任意元素影響。
應用background-blend-mode屬性後,不僅各個圖像之間要進行混合,同時還要和背景色進行混合。
接下來,講下大家可能並不知道的知識點,這也是很多人搞不清楚為什麼background-blend-mode屬性這麼渲染的原因。
二、可能不知道的1. 背景順序影響混合效果混合效果和background屬性中背景圖像的順序密切相關。在CSS多背景中,越是語法中靠後的背景圖像的層級越是低,這也是為何background-color要寫在最後語法才合法的原因,因為背景色的層級永遠是最低的。
例如下面2個元素:
<div></div><div></div>設置背景混合模式為疊加,但是兩個元素的背景圖像的順序是相反的,代碼如下所示:
.ball { width: 200px; height: 200px; border-radius: 50%; background: linear-gradient(deeppink, deeppink), linear-gradient(deepskyblue, deepskyblue); /* 應用疊加混合模式 */ background-blend-mode: overlay;}.ball2 { width: 200px; height: 200px; border-radius: 50%; background: linear-gradient(deepskyblue, deepskyblue), linear-gradient(deeppink, deeppink); /* 應用疊加混合模式 */ background-blend-mode: overlay;}結果下圖所示,.ball元素表現為deeppink疊加後面的deepskyblue,最終混合顏色偏藍;.ball2元素表現為deepskyblue疊加後面的deeppink,最終混合顏色偏紫。2. 混合效果是多個混合屬性同時作用的結果很多開發人員並不清楚,background-blend-mode支持其實是可以設置多個混合模式值,分別對應不同的背景圖像,這一點和僅僅支持一個混合模式值的mix-blend-mode屬性是不一樣的。例如:
.ball { background: linear-gradient(deeppink, deeppink), linear-gradient(deepskyblue, deepskyblue); background-blend-mode: overlay;}實際上等同於:
.ball { background: linear-gradient(deeppink, deeppink), linear-gradient(deepskyblue, deepskyblue); background-blend-mode: overlay overlay;}也就是,deeppink實際上疊加的是deepskyblue和背景色(此例是透明),deepskyblue疊加的是背景色(此例是透明)。
換言之,實際上,每個背景圖像都有一個自己的混合模式值,這是和mix-blend-mode屬性有著巨大區別的!通常,在使用mix-blend-mode屬性的場景中,我們只會把混合模式設置在頂層元素上,而不會每一層元素都設置,於是帶來了一個由此及彼的嚴重的思維誤區,以為背景混合模式設置的值也是作用在對頂層的背景圖像上的,從而導致很多開發者想不通background-blend-mode屬性的渲染表現和自己預期的不一樣。
我們通過一個案例演示下background-blend-mode屬性的多個值是如何和背景圖像一一對應的。
.box { width: 200px; height: 200px; background: linear-gradient(to right bottom, deeppink 50%, transparent 50%), linear-gradient(to top right, deeppink 50%, transparent 50%), darkblue; background-blend-mode: multiply, screen; position: relative;}/* 中間原始的deeppink色值 */.box::before { content: ''; position: absolute; width: 33%; height: 33%; inset: 0; margin: auto; background-color: deeppink;}此時.box元素總共呈現出了5種顏色,每種顏色的RGB色值和如何產生的如下圖所示。
其中:
中間標註了序號①的正方形區域沒有應用任何混合模式,顏色就是deeppink,作用是方便大家和區域③、區域⑤處的顏色進行對比。
區域②就是背景色darkblue,因為兩個斜向漸變均沒有覆蓋到這個區域,直接暴露了設置的背景色。
區域③和區域⑤是下層漸變,也就是background屬性值中位置靠後的漸變,對應的混合模式也是background-blend-mode屬性值靠後的那個,也就是screen,濾色模式,可以讓顏色變亮。
區域④和區域⑤是上層漸變,也就是background屬性值中位置靠前的漸變,對應的混合模式也是background-blend-mode屬性值靠前的那個,也就是multiply,正片疊底模式,可以讓顏色變暗。
區域③的顏色表現源自漸變色deeppink和背景色darkblue進行濾色混合的效果,可以看出最終呈現的顏色比deeppink更亮了,最終混合後的色值是rgb(255,20,206)。
區域④的顏色表現源自漸變色deeppink和背景色darkblue進行正片疊底混合的效果,可以看出最終呈現的顏色比darkblue更深了,最終混合後的色值是rgb(0,0,80)。
區域⑤最複雜,理解了這個,也就理解了大多數的background-blend-mode屬性的渲染表現了。
區域⑤總共有3層,分別是:上層的deeppink,混合模式是multiply;下層的deeppink,混合模式是screen;底層的背景色darkblue。
於是,最終的色值表現是上層的deeppink使用multiply混合下層的deeppink和背景色darkblue使用screen混合後的色值。
由於下層的deeppink和背景色darkblue使用screen混合後的色值就是區域③的顏色。因此,區域⑤的顏色就是deeppink和區域③的色值rgb(255,20,206)進行正片疊底混合後的色值,結果是rgb(255,1,119)。
以上就是.box元素5個顏色各自呈現的原理所在。
三、background-blend-mode與漸變圖標的實現最後再看看看,為何大多數人沒辦法使用background-blend-mode實現漸變圖標的效果。
例如,現在有1個顏色很深的刪除小圖標,理論上,我們可以使用lighten混合模式實現漸變效果,因為lighten的效果是哪個顏色淺使用哪個顏色,由於圖標本身顏色很深,因此,一定會顯示漸變色,只要給圖標加一個白色底就可以,於是,按照這個思路,很多人就寫了如下所示的CSS代碼:
.icon-delete { background: linear-gradient(deepskyblue, deeppink), url(delete.png), white; background-blend-mode: lighten;}乍一看,似乎邏輯上無懈可擊,漸變和白底黑色的圖標進行變亮混合,怎麼想黑色圖標也應該變成漸變色啊,很遺憾,最終的漸變並不是漸變色,而是純白色,為什麼會有這樣的結果呢?
那是因為這裡的background-blend-mode:lighten實際上是一個縮寫,或者簡寫,實際上真實的計算值是lighten lighten,代碼如下所示:
.icon-delete { background: linear-gradient(deepskyblue, deeppink), url(delete.png), white; /* 實際上的計算值 */ background-blend-mode: lighten lighten;}也就是刪除圖標delete.png也應用了混合模式lighten,和白色背景色進行了混合,於是變成了純白色。
知道了問題所在,也就知道了該如何解決了,很簡單,讓delete.png和白色背景色混合後還保持原始圖標的模樣即可,下面兩種CSS方法均可以:
.icon-delete { background: linear-gradient(deepskyblue, deeppink), url(delete.png), white; /* PNG圖標的混合模式單獨設成darken */ background-blend-mode: lighten darken;}或者是:
.icon-delete { background: linear-gradient(deepskyblue, deeppink), url(delete.png), white; /* PNG圖標的混合模式單獨設成normal */ background-blend-mode: lighten normal;}推薦使用normal關鍵字,因為更巧妙,性能也更好一點。最終實現的效果如下圖所示。
當然,漸變圖標效果最好的實現方法肯定是CSS mask遮罩屬性,這裡的使用混合模式實現的漸變圖標會有白色的底,並不是完美的實現方法,主要目的還是讓大家了解background-blend-mode屬性的渲染細節。
四、background-blend-mode的補全規則當background-blend-mode的屬性值的數量和background-image不匹配的時候,遵循下面的應用規則:
.example { background: linear-gradient(deepskyblue, deeppink), white; background-blend-mode: lighten;}.example { background: linear-gradient(deepskyblue, deeppink), white; background-blend-mode: lighten, darken;}如果background-blend-mode的值的數量少於background-image,則會重複完整的background-blend-mode屬性值進行補全,例如:
等同於:
也就是lighten, darken一起進行重複,而不是僅僅重複最後一個混合模式值。因此,補全的值的lighten。
.example { background: linear-gradient(deepskyblue, deeppink), linear-gradient(deepskyblue, deeppink), linear-gradient(deepskyblue, deeppink), white; background-blend-mode: lighten, darken, lighten;}.example { background: linear-gradient(deepskyblue, deeppink), linear-gradient(deepskyblue, deeppink), linear-gradient(deepskyblue, deeppink), white; background-blend-mode: lighten, darken;} 五、結語CSS background-blend-mode屬性可以讓各個背景圖像之間應用混合模式。
background-blend-mode屬性的使用頻率要明顯低於mix-blend-mode屬性。
原因在於:
真實世界的照片圖像很少作為background-image背景圖像呈現,因為不利於無障礙訪問,而混合模式設計的初衷就是這類照片圖像的處理;
background-blend-mode屬性作用機制不像mix-blend-mode屬性那麼單純,很多開發人員並不能很好地駕馭。例如請使用混合模式讓透明背景的小圖標變成漸變圖標,使用mix-blend-mode屬性實現的人有很多,但是能夠使用background-blend-mode屬性實現的人寥寥無幾。
因此,目前background-blend-mode屬性更常見的應用是用來豐富CSS的背景紋理,例如:
具體就不展開,非本文主要內容。
以上就是本文的全部內容,感謝閱讀,如果你覺得內容還不錯,歡迎分享。
分享前端好文,點亮 在看