用純 CSS 實現鏤空效果

UPDATE 2/26css

如今爲示例 CodePen 添加了廠商前綴,並在正文中添加了兼容性提示。感謝評論區的各位。html

近來研究了一下鏤空效果。git

background-clip: text

背景被裁剪爲文字的前景色。第一次是在 CSS-Tricks 看到的這個用法: 在 CSS-Tricks 網站上,這個玩意用獲得處都是。github

這樣,作簡單的圖片背景鏤空效果便再也不困難了。關鍵代碼只有幾行。web

.wrapper {
  /* ... */
  background-image: url("/path/to/your/image");
  -webkit-background-clip: text;  /* Chrome 用戶注意加 -webkit 前綴 */
  background-clip: text;
  color: transparent;             /* 文字設爲透明 */
}
複製代碼

就這幾行,視覺上會就會有大變化。先後對比瀏覽器

另外,這裏有個比上面更實用的 Demoapp

兼容性提示ide

除了 Firefox 和 Edge ,其它瀏覽器須要配合廠商前綴:svg

-webkit-background-clip: text;
複製代碼

background-clip 既然是「background」家族的,那它天生和圖片、漸變打的交道多。不過,咱們作鏤空總不會都是圖片、漸變這種吧。若是咱們想作視頻、文字,甚至更復雜的 DOM 元素的鏤空效果呢?動畫

單刀直入: CSS mask 屬性

這應該是最直接能想到的方法了。畢竟名字裏就帶個「mask」,誰能忽略呢?

CSS mask-* 系列屬性是在 CSS Masking Module Level 1 中定義的。這個規範也定義了爲不少人熟知的 clipclip-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 不失爲一個可行的解法。

相關文章
相關標籤/搜索