最近業務中需要實現一些鏤空的效果。看到這些效果我最初想到的是通過CSS的 mask 和 clip-path 來實現,甚至還想結合SVG相關的特性。為了驗證自己的一些想法,開始著手擼碼,但問題來了,在擼碼的過程中,我發現自己對于 mask 的相關特性理解的還不夠透徹。因此重新閱讀 CSS Masking Module Level 1規范 中的文檔和相關教程。才發現原來CSS Masking是如此的強大。下面是我自己對CSS Masking模塊的一些理解,希望對大家學習和了解該功能模塊有所幫助。
簡介
我對CSS Masking模塊的最初認知:
CSS Masking就是CSS的 mask 屬性(或 mask 相關的屬性)!
事實上,CSS Masking模塊中包含了兩個部分: masking (即: mask )和 clipping ( clip-path )。
這兩種方式都可以幫助我們實現一些類似下圖這樣的鏤空效果:

我將 Masking 譯為 遮罩 。那怎么理解遮罩呢?簡單或形象的理解,大至是這樣的一個意思:

也就是說, Masking描述了如何使用另一個圖形元素或圖像作為亮度(luminance)或alpha遮罩 。遮罩層可以是一張圖像也可以是SVG繪制的圖形,通常使用CSS或SVG渲染出來的元素(包括其子元素)會被繪制到緩沖區,然后該緩沖區將被組合到元素的父元素中。官方這段描述我個人認為過于拗口,自己簡單的理解正如上圖,圖像源和遮罩層將會創建一個緩沖區,并且源和遮罩層會有一個合成的計算,在合層階段之前,亮度和Alpha遮罩會影響這個 緩沖區 的透明度。如此得到一個類似鏤空的效果。
而 Cliping (剪切)描述了視覺元素的可見區域。可以使用某些SVG圖形或基本形狀來描述該區域。此區域之外的任何內容都將看不到。
簡單地說,該規范定義了兩種不同的圖形操作,即, 完全 或 部分 地隱藏了對象的部分。

兩者區別之處:
注意:雖然遮罩提供了許多增強圖形效果的可能性,并且通常對內容的可見部分提供了更多的控制,但是剪切路徑可以執行得更好,基本形狀可以更容易插值。
相關術語
在深入學習和了解 Masking 和 Clipping 相關的知識前,我們先了解一些有關于這方面的術語。
源對象
不管是Masking還是Clipping中都會有一個源(對象)的概念。這個源可能是一個HTML元素,比如一個 <img /> 元素。
路徑或基本圖形
在Clipping中對源對象進行剪切時,需要一個圖形,而這個圖形可以是一些基本圖形,也可以是一個閉合的矢量路徑。在CSS中,我們可以通過 clip-path 來繪制這些圖形:
正如上面示例所示,可以繪制:
inset()circle()ellipse()polygon()url()
其中 inset() 、 circle() 和 ellipse() 繪制基本圖形, polygon() 繪制多邊形,另外 url(#id) 配合SVG的 clipPath 來繪制更多圓滑的路徑(這個也被稱閉合的矢量路徑)。怎么通過這些函數來繪制圖形,后面介紹 clip-path 的時候再述。
遮罩層
在Masking中有一個遮罩層,這個遮罩層是一個圖像(漸變繪制的也是),該層也被稱為遮罩模式,主要有 高亮 和 Alpha 兩種模式。
Alpha模式:帶有 alpha 通道的圖像, alpha 通道是包含在每個像素數據中的透明度信息。最簡單的例子是帶有黑色和透明區域的PNG圖像。遮罩圖像 黑色部分 將會顯示( alpha 的值是 1 ),透明區域( alpha 的值為 0 )內容將會隱藏:

高亮模式使用圖像的 亮度 值作為遮罩值。如下圖所示,遮罩層白色區域將顯示出來,透明區域將會被隱藏:

最終得到的效果看上去相似:
Clipping
從上面的示例中,我們可以發現,剪切可以限制渲染區域,即所謂的剪切區域。從概念上講:
剪切路徑(不管是圖形還是閉合的矢量路徑)對某個元素進行剪切,將會分成兩個區域, 路徑內 (剪切區域內) 和 路徑外 (剪切區域外), 位于剪切區域內的部分可見(被繪制出來) 。
在Clipping中會用到 clip-path 、 clip-rule 和 <clipPath> :
clip-path :用來繪制圖形 clip-rule :用于確定給定點是否位于圖形元素創建的剪貼區域的形狀內的算法 <clipPath> :是SVG中的一個標簽元素,可以被用于 clip-path 的 url() 中,當作剪切路徑源
接下來了解這三個屬性。
clip-path
clip-path 主要用來創建一個只有元素的部分區域可以顯示的剪切區域, 區域內可見,區域外不可見 。其值主要有:
none :未創建任何剪切區域 <basic-shape> :CSS中繪制基本形狀的函數,常見的函數有 inset() 、 circle() 、 ellipse() 、 polygon() 、 url() 和 path() <geometry-box> :如同 <basic-shape> 一起聲明,它將為 <basic-shape> 提供相應的參考框盒子。通過自定義,它將利用確定的盒子邊緣包括任何形狀邊角(比如說,被 border-radius 定義的剪切路徑)
<geometry-box> 提供的框盒模式主要有:
margin-box :使用 margin box 作為引用框。其主要由 margin 的外部邊緣包圍的形狀。這種形狀的圓角半徑由相應的 border-radius 和 margin 的值來決定。如果 border-radius 和 margin 的比是 1 或更大,則邊距框( margin-box )的半徑是 border-radius + margin 。反之,如果兩者的比小于 1 ,那么邊距框的半徑是 border-radius + (margin * (1 + (ratio-1)^3)) ( ratio 是 border-radius 和 margin 的比,即 border-radius / margin ) border-box :使用 border box 作為引用框。定義了 border 外部邊緣包圍的形狀,此形狀遵循 border 外部邊緣所有常規的 border-radius 規則 padding-box :使用 padding box 作為引用框。定義了 padding 外部邊緣包圍的形狀,此形狀遵循 padding 外部邊緣所有常規的 border-radius 規則 content-box :使用 content box 作為引用框。定義了 content 外部邊緣包圍的形狀,此框的每個 border-radius 都大于 0 或 border-radius - border-width - padding fill-box :利用對象邊界框作( Object bounding box )為引用框 stroke-box :使用筆觸邊界框( Stroke bounding box )作為引用框 view-box :使用最近的 SVG視窗(Viewport) 作為引用框。如果 viewBox 屬性被指定來為元素創建SVG視窗,引用框將會被定位在坐標系統的原點,引用框位于由 viewBox 屬性建立的坐標系的原點,引用框的尺寸用來設置 viewBox 屬性的寬和高
如果是一個HTML元素被剪切,可以使用 margin-box 、 border-box 、 padding-box 或 content-box 框盒模式;如果運用于一個SVG元素上,可以使用 fill-box 、 stroke-box 或 view-box 。
先來看繪制基本函數的使用。

inset()
inset() 用來繪制矩形,或者帶圓角的矩形。
clip-path: inset( <length-percentage>{1,4} [ round <'border-radius'> ]? )<length-percentage> 用來設置剪切區域距離上、右、下和左側外邊緣的距離;可以設置一個、兩個、三個或四個值。
如果設置一個值,表示上右下左四個值相等;如果設置兩個值,表示上下取第一個值,左右取第二個值;如果取值三個值,表示上取第一個值,左右取第二值,下取值第三個值;
如果取值四個值,表示上取第一個值,右取第二個值,下取第三個值,左取第四個值。類似于 border 的取值 round 用來設置裁剪區域是否帶圓角,未顯式設置表示剪切區域沒有圓角,如果設置表示剪切區域帶有圓角 <border-radius> 用來設置 border-radius 的半徑值,其使用和CSS的 border-radius 一樣,也可以帶 /
用張圖來表示:

來看個Demo:
circle()
circle() 用來繪制圓。
clip-path: circle(<shape-radius> at posX posY)
<shape-radius> :圓的半徑,其值可以是 <length-percentage> 、 closest-side 、 farthest-side at :顯式的設置圓心的位置,如果未顯式設置,默認的圓心在元素的正中間,即 center ( 50% 50% ) posX posY :設置圓心位置, posX 是 x 軸的位置, posY 是 y 軸的位置,取值可以類似于 background-position
ellipse()
ellipse() 用來繪制橢圓:
clip-path: ellipse( [ <shape-radius>{2} ]? [ at <position> ]? )<shape-radius> :橢圓的半徑,其值可以是 <length-percentage> 、 closest-side 、 farthest-side ,如果只取一個值的時候,表示 x 軸和 y 的半徑值是一樣的
at :顯式的設置圓心的位置,如果未顯式設置,默認的圓心在元素的正中間,即 center ( 50% 50% )
<position> :即 posX posY ,用于設置圓心位置,如果未顯式設置,其圓心在元素正中間 (center) 即 50% 50% ,其使用類似于 background-position
polygon()
polygon() 主要用來繪制不規則的多邊形:
clip-path: polygon( <fill-rule>? , [ <length-percentage> <length-percentage> ]# )
<fill-rule> :填充規則,后面介紹 clip-rule 規則會細節,具體解釋可以閱讀 SVG中的 fill-rule 相關的規范<length-percentage> <length-percentage> 設置多邊形點的位置一個多邊形至少會有三個點組成,比如簡單的三角形,如果使用 polygon() 來繪制一個三角形的話,那么就會有三對坐標點,每對之間用一個 , 分隔,比如:

新聞熱點
疑難解答