iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 22
1
Modern Web

CSS Secrets 導讀系列 第 22

Secret 17: 改變色調

當你有一些形式各異的照片,卻要讓它們具有視覺上的一致性,一個常用且優雅的做法是先將照片灰階化,再加上同一種色調。在網頁設計上,會先在照片加上這種效果,然後在hover的時候移除,讓網頁有互動性。

以往我們會用影像處理軟體製作二種版本的圖片,寫簡單的CSS在hover的時候替換,這個方法實際有效,但是一口氣增加不少HTTP requests,更不用說管理上的麻煩,想像當主管跟你說「我覺得圖片應該再調亮一點,就這麼做吧!」你得修改所有的照片,以及調過色的版本!

其他的方法包括在照片上覆蓋半透明的色塊,或者調整照片的透明度,這些都不是真的調色,同時也減少了照片的對比。

也有一些函式庫把照片轉成<canvas>然後用JavaScript來加上色調,雖然這就是真的在調色了,不過這個方法在效能上也比較慢而且限制多。

如果直接用CSS就能調色,該有多好?

https://ithelp.ithome.com.tw/upload/images/20181106/20091606YOofZRs5TY.png
(我們的原始圖片,日本奈良春日神社附近閒晃的小鹿)


CSS Filters

因為沒有用單一個filter就能調色的功能,因此我們串接一些filters來看看。

第一個用的是sepia(),它會給照片加上「低飽和度(saturation, 即為HSL中的S)和黃橘色」的色調,常在復古的照片中看到,它會讓照片中的像素有35-40的色相值(hue, 即為HSL中的H)。如果我們需要飽和度更高的效果,就串接saturation()filter。最後用hue-rotate()filter來調整色相。

https://ithelp.ithome.com.tw/upload/images/20181106/20091606TYyzKWTznN.png
(加入sepia filter)

https://ithelp.ithome.com.tw/upload/images/20181106/20091606DGUOX7JKzu.png
(再加入saturation filter)

https://ithelp.ithome.com.tw/upload/images/20181106/20091606n8C6myoeK2.png
(最後加入hue-rotate filter)

到了這裡,我們已經為照片調色,也可以將套用效果前後的結果用在:hover

img {
	transition: .5s filter;
	filter: sepia() saturate(4) hue-rotate(295deg);
}

img:hover,
img:focus {
	filter: none;
}

色相、飽和度簡介
簡單的色彩學(英語)

CodePen


混合模式

雖然上一個方法可以用,但是結果和在影像處理軟體裡做出來的不大一樣,我們調過色的照片看起來有洗白的感覺,細節不太明顯,而且怎麼調整參數看起來都不大對。好在我們有另一個更好的方法!

https://ithelp.ithome.com.tw/upload/images/20181106/20091606cBOhC7ce2B.png
(左邊是用前面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;
}

CodePen

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;
}

CodePen

不過這個方法的缺點是:

  • 需要元素的寬高明確的定義在CSS裡。或至少有外層容器的尺寸能依賴,因為background-image是沒有尺寸。
  • background-image沒有語意上的意義,視障人士用螢幕閱讀器就無法得知內容。

如同人生大多事物,沒有一個完美的方法能做到調色效果,這一篇介紹的三個方法都能做到但各自有其優缺點,要用哪一種取決於你的專案需求。


上一篇
Secret 16: 異常的陰影
下一篇
Secret 18: 毛玻璃效果
系列文
CSS Secrets 導讀30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言