UPDATE 2/26
現在為示例 CodePen 新增了廠商字首,並在正文中新增了相容性提示。感謝評論區的各位。
近來研究了一下鏤空效果。
background-clip: text
背景被裁剪為文字的前景色。第一次是在 CSS-Tricks 看到的這個用法: 在 CSS-Tricks 網站上,這個玩意用得到處都是。
這樣,做簡單的圖片背景鏤空效果便不再困難了。關鍵程式碼只有幾行。
.wrapper {
/* ... */
background-image: url("/path/to/your/image");
-webkit-background-clip: text; /* Chrome 使用者注意加 -webkit 字首 */
background-clip: text;
color: transparent; /* 文字設為透明 */
}
複製程式碼
就這幾行,視覺上會就會有大變化。前後對比:
另外,這裡有個比上面更實用的 Demo
相容性提示
除了 Firefox 和 Edge ,其它瀏覽器需要配合廠商字首:
-webkit-background-clip: text; 複製程式碼
background-clip
既然是“background”家族的,那它天生和圖片、漸變打的交道多。不過,我們做鏤空總不會都是圖片、漸變這種吧。如果我們想做視訊、文字,甚至更復雜的 DOM 元素的鏤空效果呢?
單刀直入: CSS mask
屬性
這應該是最直接能想到的方法了。畢竟名字裡就帶個“mask”,誰能忽略呢?
CSS mask-*
系列屬性是在 CSS Masking Module Level 1 中定義的。這個規範也定義了為很多人熟知的 clip
和 clip-path
屬性,換句話說,這個CSS 模組包括遮罩和剪裁兩部分。
第一個例子
雖然是一個新的屬性,但設定 mask 屬性並不難。下面就是我們的第一個例子。
<div class="masked" />
複製程式碼
.masked {
height: 100px;
width: 100px;
background: linear-gradient(red, orange, yellow, lightgreen, blue, purple, red);
-webkit-mask: url("https://github.githubassets.com/pinned-octocat.svg");
mask: url("https://github.githubassets.com/pinned-octocat.svg");
}
複製程式碼
就是下面的效果啦。
上面的用法還是很簡單的,我們指定了一個 mask
引數,它的值是一張從GitHub盜的SVG圖片。於是多彩的漸變就被裁剪遮罩成了那隻著名的貓。
相容性提示
目前 Mask Module 還處於 Candidate Recommendation 狀態,不少瀏覽器現在需要廠商字首。Chrome 使用者和 Edge 使用者請加上
-webkit
字首,如-webkit-mask: ... ;
。Firefox 可直接使用。從Can I Use 可以知道,加上
-webkit
,支援 Mask 的瀏覽器還是不少的。為了方便閱讀,下面的程式碼 均未 使用字首。
mask-* 大家族
mask
屬性實際上是諸多mask-*
的縮寫:
mask-image
mask-repeat
mask-position
mask-clip
mask-origin
mask-size
-
mask-type
mask-composite
mask-mode
複製程式碼
有沒有 background-*
的即視感?沒錯,裡面的不少屬性都是和 backgorund / border 一致的,而且它們的作用也是一致的,只不過 background-*
用在背景上,而 mask-*
用在遮罩層上而已——用在背景上的奇技淫巧搬到 mask 的世界裡還能接著用!比如實現這樣的效果:
.masked {
height: /* ... */;
width: /* ... */;
background: /* ... */;
/* Webkit 核心使用者請注意新增廠商字首 -webkit */
mask-image: url(https://github.githubassets.com/pinned-octocat.svg);
mask-size: 5em;
mask-position: center;
/* 如果你心情好,加個動畫也沒問題的 */
}
複製程式碼
進一步控制遮罩效果
可能讀者已經發現了,mask-*
家族裡有幾張生面孔。這也好理解: mask 這麼強大的特性,完完全全地抄 background-*
豈不可惜了。
mask-mode
mask-mode 用來指定具體的遮罩方式。
相容性預警:目前
mask-mode
僅 Firefox 53+ 支援。
mask-type CSS 屬性設定 mask-image
被用於“亮度型”的遮罩還是“不透明度”型的遮罩。mask-mode: alaph
表示使用不透明度(即alaph通道)作為 mask value,mask-mode: luminance
表示使用亮度值作為 mask value。
那,遮罩值 / mask value 又是什麼?mask value 表示被遮罩的元素被遮罩的程度。mask value 越大,被遮罩區域會更偏向於顯露,mask value 最大的時候,那個區域就完全不透明瞭。舉個例子:
<div class="mode">ABCDEFG</div>
複製程式碼
.mode {
height: 200px;
width: 300px;
/* and more */
mask-image: linear-gradient(to left, black, yellow);
mask-mode: luminance; /* or alaph ? */
}
複製程式碼
左邊是遮罩圖片,中間是 luminance
右邊使用 alaph
。這裡的圖片是不透明的,所以將一個恆不透明的圖片在alaph
模式下作為遮罩,其結果是沒有遮罩效果。但是圖片是有亮度變化的,所以luminance
下的被遮罩元素就呈現出透明度的變化了。
一般 luminance
模式慢一點點,因為每一個畫素點的亮度值需要根據 RGB 三個通道的值計算出來。
mask-composite
指定當有多個遮罩圖片疊加起來的時候,如何處理遮罩效果。一些屬性值的效果依賴於 mask-image 的層級次序。
用 MDN 提供的這個 CodePen 來感受一下
關於 mask
的知識就講到這裡,更具體更準確的說明還是要到 MDN 看一看。
混合模式
這應該是最為神奇的一種方法了。使用PS的時候,經常會看見“混合模式”這個詞。還記得多年前我初次使用 Photoshop 的時候還很好奇“混合模式”是什麼東西,頓時讓我對 Photoshop 充滿了敬畏之情。不過,當年的敬畏歸敬畏,現在這裡說的“混合模式”還是蠻好理解的。
所謂的“混合模式”,是指當一種當層重疊時計算畫素最終顏色值的方法。每種混合模式接收前景顏色值和背景顏色值(分別為頂部顏色和底部顏色)作為輸入,執行一些計算並輸出最後要顯示在螢幕上的顏色值。最終的可見的顏色是對層中的每個重疊畫素執行混合模式計算所得的結果。說白了,混合模式確定了把一層疊加到另一層上去會得到什麼結果。
在 CSS 中,可以使用 mix-blend-mode
來指定混合模式。
你可能會問了,平時也沒有用什麼“混合模式”這種東西,所以blend-mode
的預設值是none
嗎?可不是。其實,這種最常見的 上層把下層“遮住”了的情況也屬於一種混合模式,叫normal
,它本質上是一種只保留前景顏色值而完全拋棄背景顏色值的混合模式。
這裡我們只討論實現鏤空效果用到的混合模式 —— screen
。這種混合模式有一個特性,前景層是黑色導致最終可見的顏色直接是背景層的顏色,前景層是白色導致最終可見的顏色直接是白色。
相信你已經搞不明白這和鏤空有什麼關係了,下面舉個例子看一下。
現在,我們有一個<video>
,以及一個“白底黑字”的Logo浮層。
我們在浮層框上加上下面的 CSS:
.logo {
/* ... ... */
mix-blend-mode: screen;
}
複製程式碼
就變成了下面的樣子:
去這個 Demo,看具體程式碼和效果齒輪圖示確實是變為鏤空的了。不過,為什麼呢?
先來明確一件事:把浮層置於視訊之上,浮層是“前景”,視訊是“背景”。先來看浮層的白色部分,因為把白色置於任何顏色之上都得到白色,所以白色部分被保留;而因為黑色置於任何顏色之上都得到下層的顏色,所以黑色部分呈現鏤空效果。
但是這樣的實現比較 Hack,因為這裡只使用了黑白兩色,如果使用其它的顏色作為浮層的 background-color
,得到的就不會像是鏤空的效果了,這時還是得請上面的mask
家族出場。不過,單單對於白底的情況,mix-blend-mode
不失為一個可行的解法。