iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 23
1

毛玻璃效果是指用一層半透明的色片覆蓋複雜的背景,讓在毛玻璃前面的文字能容易閱讀。會這麼做是因為在背景裡有些有趣的地方,我們希望保留給使用者看得見,同時也要讓在前面的文字容易閱讀。

<main>
  <blockquote>
    "Sometimes I think I have felt everything I'm ever gonna feel. And from here on out, I'm not gonna feel anything new. Just lesser versions of what I've already felt."
    <footer>-
      <cite>
        Theodore, Her (2013)
      </cite>
    </footer>
  </blockquote>
</main>
body {
  background: url(http://drive.google.com/uc?export=view&id=1ycTKvTds3B6SLQc44VqFAVp6ZY998P3E) 0 / cover fixed;
}

main {
  background: hsla(0,0%,100%,.3);  
}

https://ithelp.ithome.com.tw/upload/images/20181108/20091606r8p8LAsSHI.png
(簡單的毛玻璃效果,文字看不太清楚)

但遇到極為複雜的背景時,簡單的毛玻璃無法突顯文字,如果我們減少毛玻璃層的透明度(提高alpha值,等同於減少透光度),雖然文字看清楚了,但也擋住了背景,讓畫面看起來少了趣味。

main {
  background: hsla(0,0%,100%,.8);  
}

https://ithelp.ithome.com.tw/upload/images/20181108/2009160689ezA6OOX2.png
(增加了背景的不透明度,同時也擋住了背景圖片)

在平面印刷設計上的解法是只把文字區塊的背景做模糊效果,模糊後的背景比較不複雜,讓文字容易閱讀。不過因為模糊化是個很耗運算資源的效果,以往在網頁和UI設計是被禁止的。然而近年來因為GPU和硬體加速愈來愈普及,模糊化後的毛玻璃效果也愈常見到。過去幾年我們能在微軟Windows以及蘋果的iOS和macOS看到毛玻璃效果被用在作業系統的介面。

我們也得到在CSS裡對元素進行模糊的能力,透過blur()filter,CSS也有了SVG一向擁有的功能。然而如果我們直接對我們範例中的文字區塊用blur()的話,整個元素都被模糊化了,根本就不知道文字在寫什麼。有沒有什麼方法可以只模糊文字區塊的背景呢?

main {
  background: hsla(0,0%,100%,.3);  
  filter: blur(3px);
}

https://ithelp.ithome.com.tw/upload/images/20181108/200916062V3uzQREGz.png
(用了blur()後更糟)


我們的解決方法靈感來自前面提到的平面印刷,但是blur()又不能用在文字區塊上,所以我們用文字區塊的偽元素做一個一模一樣大小的背景圖,blur()就用在這個偽元素上所以不會影響到文字,然後再將它移到文字區塊後面。

首先做一個偽元素,然後用absolute定位,讓它蓋過整個文字區塊(也就是<main>)。

main {
	position: relative;

	/* 其他的樣式 */
}

main::before {
  content: '';
  position: absolute;
  top:0; right:0; bottom:0; left:0;
  background: rgba(255,0,0,.5); /* debug用的紅色背景 */
}

https://ithelp.ithome.com.tw/upload/images/20181108/200916065TFx6ZDYiz.png
(紅色的偽元素擋在內容前面)

我們把要模糊化的偽元素背景先用紅色背景色代替,這樣比較好理解,不然透明的背景我們什麼也看不到,出錯了根本不知道錯在哪裡。

這時明顯的看到,偽元素背景現在是覆蓋在內容之上,所以我們用z-index: -1把它移到後面去。

現在是時候將紅色換成我們的背景圖,然後加上模糊效果。

https://ithelp.ithome.com.tw/upload/images/20181108/20091606WBzbZhufue.png

看起來不賴,文字區塊中心的模糊效果很好,但是愈接近邊緣模糊的程度就不是那麼強。對blur radius原理「高斯模糊」可以看這裡的解釋,簡單來說這個「模糊半徑」愈長,圖片平滑的效果愈好,但因為高斯模糊是以常態分佈來分配權重,於是愈靠近中心的像素權重愈高,模糊效果愈強,反之愈遠離則愈弱。如果我們把前面清除的紅色背景加回來,就能清楚的發現效果強弱的分佈。

https://ithelp.ithome.com.tw/upload/images/20181108/20091606QT6IZkfGlW.png
(從紅色背景可以看出模糊效果的強弱分佈)

為了讓毛玻璃有平均的模糊程度(你有看過透明度不一的毛玻璃嗎?),我們把偽元素尺寸加大,每邊至少margin: -20px,和blur radius相等,避免不同瀏覽器對blur的演算法不同而破壞我們的畫面。這時可以看到模糊效果超出了文字區塊,在文字區塊加上overflow: hidden就可以了。

body, main::before {
  background: url(http://drive.google.com/uc?export=view&id=1ycTKvTds3B6SLQc44VqFAVp6ZY998P3E) 0 / cover fixed;
}

main {
  background: hsla(0,0%,100%,.3);  
  position: relative;
  overflow: hidden;
  
  /* 其他樣式 */
}

main::before {
  content: '';
  position: absolute;
  top:0; right:0; bottom:0; left:0;
  filter: blur(20px);
  z-index: -1;
  margin: -30px;
}

https://ithelp.ithome.com.tw/upload/images/20181108/20091606UPuw8kO4Vr.png

最後加上一些陰影和文字效果,毛玻璃就大功告成了。

CodePen
註:文章寫完才覺得最後的成果跟一開始增加alpha值的效果差不多,所以在CodePen裡把blur-radius減少到5px,因為我的文字區塊其實不大,原本照書中設的20px值太大了。不過圖也貼了,就懶得改,等以後修訂時再來訂正吧。


上一篇
Secret 17: 改變色調
下一篇
Secret 19: 折角效果
系列文
CSS Secrets 導讀30

1 則留言

0
SunAllen
iT邦高手 1 級 ‧ 2018-11-07 23:57:06

/images/emoticon/emoticon07.gif
好看!

感謝支持/images/emoticon/emoticon01.gif

SunAllen iT邦高手 1 級 ‧ 2018-11-08 00:36:51 檢舉

一直在看啊!

感動ing~

我要留言

立即登入留言