當你有一些形式各異的照片,卻要讓它們具有視覺上的一致性,一個常用且優雅的做法是先將照片灰階化,再加上同一種色調。在網頁設計上,會先在照片加上這種效果,然後在hover
的時候移除,讓網頁有互動性。
以往我們會用影像處理軟體製作二種版本的圖片,寫簡單的CSS在hover
的時候替換,這個方法實際有效,但是一口氣增加不少HTTP requests,更不用說管理上的麻煩,想像當主管跟你說「我覺得圖片應該再調亮一點,就這麼做吧!」你得修改所有的照片,以及調過色的版本!
其他的方法包括在照片上覆蓋半透明的色塊,或者調整照片的透明度,這些都不是真的調色,同時也減少了照片的對比。
也有一些函式庫把照片轉成<canvas>
然後用JavaScript來加上色調,雖然這就是真的在調色了,不過這個方法在效能上也比較慢而且限制多。
如果直接用CSS就能調色,該有多好?
(我們的原始圖片,日本奈良春日神社附近閒晃的小鹿)
因為沒有用單一個filter就能調色的功能,因此我們串接一些filters來看看。
第一個用的是sepia()
,它會給照片加上「低飽和度(saturation, 即為HSL中的S)和黃橘色」的色調,常在復古的照片中看到,它會讓照片中的像素有35-40的色相值(hue, 即為HSL中的H)。如果我們需要飽和度更高的效果,就串接saturation()
filter。最後用hue-rotate()
filter來調整色相。
(加入sepia filter)
(再加入saturation filter)
(最後加入hue-rotate filter)
到了這裡,我們已經為照片調色,也可以將套用效果前後的結果用在:hover
img {
transition: .5s filter;
filter: sepia() saturate(4) hue-rotate(295deg);
}
img:hover,
img:focus {
filter: none;
}
雖然上一個方法可以用,但是結果和在影像處理軟體裡做出來的不大一樣,我們調過色的照片看起來有洗白的感覺,細節不太明顯,而且怎麼調整參數看起來都不大對。好在我們有另一個更好的方法!
(左邊是用前面CSS filter,右邊是用混合模式做的結果,比較起來右邊的細節比較清楚)
如果你有用過Photoshop,你應該知道它有個功能叫「混合模式(blend mode)」,當二個影像重疊時,混合模式會決定上層的圖像要如何與下層圖像混合。當要為圖像上色時要使用luminosity這個模式,它會保留最上層圖像的亮度,然後使用下層圖像的色相和飽和度。這就是我們要的效果。
在用混合模式時有二個屬性可以用:mix-blend-mode
將效果套用在整個元素;background-blend-mode
則可以為每一個背景圖層分別加上效果,它的順序要和background-image
裡的圖層順序一致。
因此我們有二種方法可以實現調色效果,可惜沒有一種是完美的。
第一個方法是把luminosity
用在父層容器,裡面包<img>
,並且在父層容器加上我們要的顏色當做background-color
。
<a href="#" class="tinted-image">
<img src="http://drive.google.com/uc?export=view&id=1ycTKvTds3B6SLQc44VqFAVp6ZY998P3E">
</a>
.tinted-image {
background: hsl(335, 100%, 50%);
}
.tinted-image img {
mix-blend-mode: luminosity;
}
Blending mode和CSS filter一樣有優雅降級的特性,也就是說如果瀏覽器不支援對影像不會造成影響。
然而blending mode不像CSS filter能套用動態效果,前面我們練習過使用CSS transition在:hover
的時候讓照片從單色調漸變成彩色,但是在blending mode的例子裡卻不能用。不過這不表示我們就不能加動態效果了。
mix-blend-mode
將效果套用在整個元素,所以圖像下面一定要有某個東西不然就不能混合了。而background-blend-mode
則是指定任一個圖層與其下層的圖層混合的方式,不管其他圖層如何設定。想像一下當我們只有一個圖層,而它的背景又是個透明圖層的話會有什麼效果?沒錯,就跟沒有用混合效果一樣!
於是我們可以利用這個發現,在這裡使用background-blend-mode
屬性。不過圖片就不能以<img>
加入網頁,要用background-image
的方式。然後只要在元素上套用CSS樣式,在:hover
時把背景色改成透明。這個方法不需要額外的元素。
<div class="tinted-image"></div>
.tinted-image {
background-image: url(http://drive.google.com/uc?export=view&id=1ycTKvTds3B6SLQc44VqFAVp6ZY998P3E);
background-size: cover;
background-color: hsl(335, 100%, 50%);
background-blend-mode: luminosity;
width: 640px;
height: 480px;
transition: .5s background-color;
}
.tinted-image:hover {
background-color: transparent;
}
不過這個方法的缺點是:
background-image
是沒有尺寸。background-image
沒有語意上的意義,視障人士用螢幕閱讀器就無法得知內容。如同人生大多事物,沒有一個完美的方法能做到調色效果,這一篇介紹的三個方法都能做到但各自有其優缺點,要用哪一種取決於你的專案需求。