CSS mix-blend-mode 與 Photoshop 圖層混合功能對照
圖左有一組清單,標題跟內文各有背景色,清單上面有一些透明圖案,會跟標題和內文的背景色混合。
只是把圖存成 PNG 蓋在上面肯定是不可行的,因為要跟底下其他區域混合後,才會是正確的顏色。
也無法把圖案墊在最下面,會被標題跟內文的背景圖蓋住,當然顏色也會不對。
用 RWD 的思考邏輯,肯定無法把圖案切開直接做在那幾個標題跟內文裡面,因為螢幕寬度改變時,標題與內文可能會換行或變少一行,高度就不一樣了,還有螢幕比較小時,容器外間距跟圖形肯定不會留這麼大,圖形的大小位置都會改變。
圖右有幾顆圖片造型按鈕,上面蓋著一些不可以斷掉的造型圖形,
除了跟上面幾點差不多的問題,用 RWD 的思考邏輯,螢幕寬度不同時,按鈕文字可能會改變,按鈕左右內距可能會改變,按鈕之間的距離可能會加大或縮窄。
看來又要出動 CSS 的圖層混合模式了。
什麼是圖層混合模式?
圖層混合模式並不是 Photoshop 特有的東西,illustrator 和其他 Adobe 全家餐幾乎都有,基本上不管是市面上的商業軟體或開源軟體,稍微完整的數位影像工具(繪圖/影片/影像處理…)都會有這功能,這算是計算機圖學的東西,沒有誰抄誰的問題。
簡單來說就是每一種圖層混合模式都有一組數學公式,讓重疊區域的像素,透過一些 RGB 數值的加減乘除,得到不同的顯示效果。
更詳細的說明可以參考:
- 維基百科 Blend modes
- Adobe 官方介紹 Adobe Photoshop 混合模式說明
- 每一種混合模式的數學公式,可以在 google 搜尋 blend mode formula,找一篇自己看得懂的。
圖層混合模式的應用
純視覺設計做圖的應用,例如一些玻璃杯/水晶球與背景照合成、合成湖面倒影、陰影、火焰、煙霧、假去背的時候都會用到,有些設計人員可能會看過 ai 檔案裡有星芒圖案,但是把背景拿掉之後卻變成一團黑黑的漸層,都是用了圖層混合模式。
網頁上的應用也不少,自從 IE 瀏覽器死透了之後,我也已經用了好幾次混合模式,但都是用在一些神奇的用途,例如:
– 如本例,原稿設計時就使用圖層混合模式,而且 RWD 設計上無法直接整張平面化拿去用。
– 滑鼠移入或點擊時讓圖片有個效果,可以讓圖長得不一樣,但又不用額外多做一張圖,css filter 或 mask 也可以用。
– 類似假浮水印或改色調的用途,直接讓網頁裡的圖片顯示成另一個樣子,就不用全部重新做圖上傳。
– 網頁前景有個動態效果,用各種方法實作,最後是 mp4 檔案最小,想要拿掉影片的黑底或白底背景,讓網頁本身的背景圖片顯示出來。
video tag 放 webm 影片 Alpha transparency in Chrome video – Chrome Developers 看似可以達成需求,但是在 iOS Safari 有瀏覽器相容性問題無法正常顯示,最後用 mix-blend-mode 成功硬幹出來(僅適用於影片裡的主體有一個固定不動的形狀),不過這種需求應該也可以用瀏覽器支援性更差的 css mask。
蘋果官網在某一段時間開始也很常用,例如 iPhone 14 這個網頁第一段的文案,隨著捲動時整塊區域的文字有不同顏色的效果。
不過有些人都覺得這個只是把字擺上去,字這麼大,像是在做 PPT,壓根不覺得技術上有什麼特別的。
大致就是蘋果的網頁在網頁上弄了一塊紫色漸層,
在某一區間捲動網頁時,另外控制讓文字固定住,
只有紫色漸層區塊會蓋在字上面,隨著網頁捲動(如上圖上半部),
然後透過 blend-mode 和文字混色(如上圖下半部),
超出區域後,固定的文字會再恢復成隨網頁捲動。
跟只是單純把每一行文字選取起來 設定文字顏色、頁面上所有東西都隨著網頁捲動的效果…完全不同。
只有一些經常看國外設計網站,還有可憐的基層人員才看出箇中趣味。
可憐的基層人員就是像是我這種寫網頁的,客人丟一個網頁來就要想辦法評估可行性和復刻。
或是一些公司買了業務講得飛天遁地,號稱什麼都可以做的網頁拖曳區塊編輯器,但實際負責操作的行政文書人員發現一堆效果還是根本做不出來。
CSS 混合模式的問題 1 – 比 PS 少很多
回到開頭的問題,要把繪圖軟體裡用到的效果實作在網頁上,最大的一個問題:
Photoshop CC 2023(v24) 的圖層混合模式選單裡面,不算「正常(normal)」的話,選項有 26 個
但是瀏覽器支援的 CSS mix-blend-mode 的屬性值,照 MDN docs 文件,排除 unset, initial, normal, inherit,PS 沒有的 plus-lighter, plus-darker, revert, revert-layer 也先不算,現階段總共只有 15 個。
兩邊數量根本對不起來,那要怎麼實作設計呢?
以下用 Photoshop 繁體與 CSS mix-blend-mode 的屬性值做個對照,簡體中文版名詞只列 CSS mix-blend-mode 有的
Photoshop 混合模式名稱 | 簡中 | mix-blend-mode |
---|---|---|
穿過 | 無 | |
溶解 | 無 | |
變暗 | 變暗 | darken |
色彩增值 | 正片疊底 | multiply |
加深顏色 | 顏色加深 | color-burn |
線性加深 | 無 | |
顏色變暗 | 無 | |
變亮 | 變亮 | lighten |
濾色 | 濾色 | screen |
加亮顏色 | 顏色減淡 | color-dodge |
線性加亮(增加) | 無 | |
顏色變亮 | 無 | |
覆蓋 | 疊加 | overlay |
柔光 | 柔光 | soft-light |
實光 | 強光 | hard-light |
強烈光源 | 無 | |
線性光源 | 無 | |
小光源 | 無 | |
實色疊印混合 | 無 | |
差異化 | 差值 | difference |
排除 | 排除 | exclusion |
減去 | 無 | |
分割 | 無 | |
色相 | 色相 | hue |
飽和度 | 飽和度 | saturation |
顏色 | 顏色 | color |
明度 | 亮度 | luminosity |
線性加深(linear burn)、顏色變暗(darker color)、線性加亮(增加)(linear dodge(add))、強烈光源(vivid light)、減去(subtract)、分割(divide)都是繪圖軟體有,但是 CSS 沒有的。
運行在網頁瀏覽器內的 UI 設計軟體 Figma,也只有提供那些 css 有的圖層混合選項。
不過從一些 N 年前的文章發現有人照那些圖層混合算法寫 js 產生 canvas,有興趣的人可以參考看看
– PhotoShop图层混合模式的Canvas实现 有列出一些混合模式的公式算法
– Image Blend modes and HTML Canvas 把開頭載入圖片的 error 修掉之後,還是無法如預期照公式算法產生想要的圖片
– Adding color-dodge/divide blending mode in fabric.js 這個範例是單張圖與一個顏色做混合,跟本文需求不一樣,不過 fabric.js 版本也太舊了
CSS 混合模式的問題 2 – 各種瀏覽器相容性問題
還是那句,不出意外的話就要出意外了。
這邊放個簡單的 demo,主要就是把三張不透明的圓形圖片,透過圖層混合模式讓重疊的部分混色,各大類混合模式各挑了一個做代表,然後圓形圖片分別是 png, svg tag, svg 放在 img tag。
iOS 又跟別人顯示得不一樣,外容器要另外多加 isolation:isolate
,才會跟別的瀏覽器顯示得一樣,以免又不知道混色混到哪裡去了。
然後在客人那邊的 Macbook 會出現類似破圖的情況,顯示出來的不是原圖沒混合的樣子,也不是任何一種圖層混合效果,完全變成一種全新的特效。在我這邊的 macOS 設備都無法重現,而且通常重新整理又會正常顯示,所以無法像發現新的星星一樣命名。
排查問題:
– 新舊款筆電機型都有機會,也跟瀏覽器版本啥的無關,就我自己碰不到。
– 問題圖片都是 png,所以應該跟 jpg 圖片轉存時選 Progressive 還是 Baseline 無關。
– 有多處使用 mix-blend-mode,但是剛好 mix-blend-mode: color-dodge 的出問題? 不知道是巧合還是 bug。
– 沒有用到其他會觸發 The stacking context 的屬性,code 本身應該沒問題。
– 圖片沒有做 css animation 或其他效果,所以跟 Chrome css3 mix blend mode bug in chrome 可能沒什麼關係。
結論
除了瀏覽器相容性問題,如果是像本次現實使用需求,會把圖蓋在可操作的 UI 元件上,記得要設 z-index 或 points-events,以免做出看得到但點不到的按鈕。
CSS 除了 mix-blend-mode,還有更加複雜的 background-blend-mode,就跟 background 屬性一樣可以設定多組值,常看到國外的神人拿 background-blend-mode 搭配 linear-gradient 拿來做出各種圖案的背景圖,讓人讚嘆數學好的人真的是可以為所欲為。
額外加戲:網路上的迷因圖
在好色龍 – 雜七雜八短篇漫畫翻譯1842 看到一張有趣的圖,一張長得像 CMY 混色圖的加上一堆線,看起來就能讓人產生幻覺?
由於圖片上傳到社群網站會壓縮圖片,還有圖片會平滑化,圖片中白色的地方去吸顏色肯定不是純白的(#FFFFFF, rgb:255,255,255)。那些線段肯定也不是單一藍色或單一黑色,我另外做了個網頁來玩玩。
上面那個框框往下捲動可以看到兩個實驗範例:
實驗1:只是單純在青色和洋紅圈圈上面加上一堆藍色的線,就會讓人覺得右下角有一個黃色的圓?
如果把右下那個圓改成白色,會發現右下角什麼都沒有。
實驗2:只是單純畫一堆藍色和黑色的線條,就能讓人覺得中間有一個黃色的圓? 可以調整畫面上的藍色線段寬度試試。
原圖的奧秘應該在那些藍色線段,有一區塊是黑色的,應該是補色的關係。