影像遮罩 mask
所謂的「遮罩」泛指一個形狀區域,透過形狀可以看見元素的內容,而形狀外的內容就會被遮住,這篇教學會介紹 CSS 遮罩相關樣式屬性,例如 mask、mask-image、mask-mode、mask-position、mask-clip、mask-origin、mask-repeat、mask-size、mask-type 等遮罩相關樣式屬性。
CSS 遮罩的
mask-type
屬於 SVG 元素的樣式屬性,在本篇教學中不會介紹,有興趣可以參考這篇文教學:SVG 研究之路 (9) - Clipping and Masking
快速導覽:
認識遮罩
「遮罩」泛指一個形狀區域,透過形狀可以看見元素的內容,而形狀外的內容就會被遮住,就如同透過一個具有形狀的不透明紙板看影像,在許多繪圖軟體中,遮罩是幾乎是必備的功能,透過遮罩,可以快速實現。
CSS 的遮罩和 clip-path
裁切路徑的效果有點類似,但仍有下列的差異:
差異 | 遮罩 | clip-path |
---|---|---|
定義範圍 | 影像 | 長度或座標 |
透明度 | 可設定透明度、漸層遮罩 | 不支援透明度,單純剪裁出範圍 |
動態改變範圍 | 無法動態改變範圍,需要改變遮罩圖片內容 | 改變座標就可動態改變範圍 |
mask-image 影像遮罩
mask-image
樣式屬性可以指定一張圖片作為「遮罩圖片」,用法和 background-image
相同,沒有繼承特性,支援 jpg、png、SVG 以及使用 CSS 漸層,在 mask-mode: luminance
模式下,瀏覽器會將圖片轉換成「灰階」影像,根據影像中的「黑白程度 ( 亮度 )」決定遮罩的透明度,「越黑」越透明,「越白」越不透明,如果圖片有透明度則根據透明度決定遮罩是否透明。如果是 mask-mode: alpha
模式,則會根據影像中的「透明度」決定遮罩的透明度,由於 jpg 影像沒有透明度,使用透明度作為遮罩會完全沒有作用。
注意,元素所有一切,包含邊框、陰影都會被遮罩所遮住。
下方範例會使用 mask-mode: luminance
模式,讓四種不同格式圖片產生遮罩效果。
<!-- HTML 程式碼-->
<div></div><div></div>
<div></div><div></div>
<div></div><div></div>
<div></div><div></div>
<!-- CSS 程式碼 -->
<style>
div {
width:500px;
height: 210px;
margin: 20px;
float: left;
mask-mode: luminance; /* 設定遮罩圖片為亮度模式 */
background: url('https://steam.oxxostudio.tw/image/index-css.jpg');
}
div:nth-child(2n+1) {clear: both;}
div:nth-child(1) {background: url('https://steam.oxxostudio.tw/download/css/mask-demo-01.png');}
div:nth-child(2) {mask-image: url('https://steam.oxxostudio.tw/download/css/mask-demo-01.png');}
div:nth-child(3) {background: url('https://steam.oxxostudio.tw/download/css/mask-demo-02.jpg');}
div:nth-child(4) {mask-image: url('https://steam.oxxostudio.tw/download/css/mask-demo-02.jpg');}
div:nth-child(5) {background: url('https://steam.oxxostudio.tw/download/css/mask-demo-03.svg');}
div:nth-child(6) {mask-image: url('https://steam.oxxostudio.tw/download/css/mask-demo-03.svg');}
div:nth-child(7) {
background: repeating-linear-gradient(
to right,
white 0%, white 5%,
black 5%, black 10%
);
}
div:nth-child(8) {
mask-image: repeating-linear-gradient(
to right,
white 0%, white 5%,
black 5%, black 10%
);
};
</style>
透過漸層色的方式,甚至可以讓影像呈現「雙重背景」的有趣效果,下方範例會使用漸層作為遮罩,讓兩個 div 的背景互相重疊融合。
延伸閱讀:CSS 函式 ( 漸層色 )
<!-- HTML 程式碼-->
<div><div></div></div>
<!-- CSS 程式碼 -->
<style>
div {
width:500px;
height: 220px;
margin: 20px;
background: url('https://steam.oxxostudio.tw/image/index-css.jpg');
}
div div {
margin: 0;
background: url('https://steam.oxxostudio.tw/image/index-html.jpg');
}
div div {
mask-image: repeating-linear-gradient(
to right,
#0000 0%, #0000 10%,
#000f 90% , #000f 100%);
}
</style>
除了單一遮罩,mask-image
也支援「多重遮罩」,只需要用逗號分隔多組遮罩圖片,就能實現多重遮罩的效果,進行多重遮罩時,會採用所有遮罩圖片中「比較透明」或「比較黑」的色彩作為遮罩本身的顏色或透明度。
<!-- HTML 程式碼-->
<div></div>
<!-- CSS 程式碼 -->
<style>
div {
width:500px;
height: 220px;
margin: 20px;
background: url('https://steam.oxxostudio.tw/image/index-css.jpg');
}
div {
mask-mode: luminance;
mask-image: repeating-linear-gradient(
to right,
#000 0%, #000 5%,
#fff 5%, #fff 6%),
repeating-linear-gradient(
to bottom,
#000 0%, #000 5%,
#fff 5%, #fff 6%),
url('https://steam.oxxostudio.tw/download/css/mask-demo-01.png');
};
</style>
除了使用外部的 SVG,mask-image
也可以讀取在 HTML 裡 SVG 的 <mask>
標籤,下方範例會讀取 HTML 裡 SVG 中 id 為 myMask 的遮罩形狀,並將這個形狀作為遮罩影像,注意,讀取 HTML 裡的 SVG 的 <mask>
標籤時只支援 mask-mode: luminance;
模式。
<!-- HTML 程式碼-->
<svg>
<mask x="0" y="0" width="105.4" height="106.8" id="myMask">
<rect x="0" y="0" width="220" height="220" fill="white" />
<path fill="black" d="M97.8,13.2l-13.6,35l21.1,31l-37.5-2.1l-23,29.7l-9.6-36.3L0,57.9l31.5-20.3L32.7,0l29.1,23.7L97.8,13.2z"/>
</mask>
</svg>
<div></div>
<!-- CSS 程式碼 -->
<style>
div {
width:500px;
height: 220px;
margin: 20px;
background: url('https://steam.oxxostudio.tw/image/index-css.jpg');
}
svg {
width: 0;
height: 0;
}
path {transform: scale(2.0);} /* 放大遮罩路徑 */
div {
mask-mode: luminance;
mask-image: url(#myMask); /* 讀取遮罩路徑 */
};
</style>
mask-mode 遮罩模式
mask-mode
可以設定遮罩模式,沒有繼承特性,有下列屬性值:
屬性值 | 說明 |
---|---|
alpha | 根據透明度,影像越透明遮罩越透明。 |
luminance | 根據亮度 ( 灰階化後的黑白程度 ),顏色越黑遮罩越透明。 |
match-source | 預設值,如果是影像就用 alpha,如果是 SVG mask 標籤就用 luminance。 |
下方範例會使用預設模式的 mask-mode
,如果是影像就會自動使用 alpha,如果是 SVG mask 標籤就會使用 luminance。
<!-- HTML 程式碼-->
<svg>
<mask x="0" y="0" width="105.4" height="106.8" id="myMask">
<rect x="0" y="0" width="220" height="220" fill="#ccc" />
<path fill="black" d="M97.8,13.2l-13.6,35l21.1,31l-37.5-2.1l-23,29.7l-9.6-36.3L0,57.9l31.5-20.3L32.7,0l29.1,23.7L97.8,13.2z"/>
</mask>
</svg>
<div></div>
<div></div>
<!-- CSS 程式碼 -->
<style>
div {
width:500px;
height: 220px;
margin: 20px;
background: url('https://steam.oxxostudio.tw/image/index-css.jpg');
}
svg {
width: 0;
height: 0;
}
path {transform: scale(2.0);}
/* 使用 HTML 裡 SVG 的 mask 遮罩 */
div:nth-of-type(1) {mask-image: url(#myMask);}
/* 使用外部圖片 */
div:nth-of-type(2) {
mask-image: url('https://steam.oxxostudio.tw/download/css/mask-demo-01.png');
}
</style>
mask-repeat 遮罩重複方式
mask-repeat
可以定義「遮罩重複的方式」,使用方式和 background-repeat
完全相同,沒有繼承特性,具有下列幾個屬性值:
屬性值 | 說明 |
---|---|
repeat | ( 預設值 ) 使用遮罩圖片所設定的尺寸連續並重複出現,超過範圍的遮罩會被裁切。 |
no-repeat | 不重複,使用單一張遮罩圖片。 |
space | 使用空白分隔重複的遮罩圖片,保持原本長寬尺寸重複且不被裁切。 |
round | 修改重複的遮罩圖片的長寬比例,讓重複的遮罩圖片不被裁切。 |
repeat-x | 等同 repeat 但只在水平方向重複。 |
repeat-y | 等同 repeat 但只在垂直方向重複。 |
下列範例會讓不同的 div 呈現不同的 mask-repeat
遮罩效果。
<!-- HTML 程式碼-->
<div class="a"></div>
<div class="b"></div>
<div class="c"></div>
<div class="d"></div>
<div class="e"></div>
<div class="f"></div>
<!-- CSS 程式碼 -->
<style>
div {
width:300px;
height: 150px;
margin: 20px;
background: url('https://steam.oxxostudio.tw/image/index-css.jpg');
mask-image: url('https://steam.oxxostudio.tw/download/css/mask-demo-01.png');
mask-size: 130px 60px;
}
.a {mask-repeat: repeat;} /* 按照遮罩圖片設定尺寸重複 */
.b {mask-repeat: no-repeat;} /* 不重複 */
.c {mask-repeat: space;} /* 使用空白分隔重複的遮罩圖片,保持原本長寬尺寸重複且不被裁切 */
.d {mask-repeat: round;} /* 修改重複的遮罩圖片的長寬比例,讓重複的遮罩圖片不被裁切 */
.e {mask-repeat: repeat-x;} /* 水平重複 */
.f {mask-repeat: repeat-y;} /* 垂直重複 */
</style>
mask-position 遮罩位置
mask-position
可以定義「遮罩位置」,使用方式和 background-position
幾乎完全相同,沒有繼承特性,使用「對齊關鍵字」或「位置偏移量」來定義遮罩圖片的位置,可以將關鍵字與偏移量互相搭配,產生「1~4」個屬性值,沒有繼承特性,下列方列出相關撰寫語法:
對齊關鍵字
單純使用位置名稱進行對齊,這個寫法會有「1~2」個屬性值,使用後表示會將遮罩圖片的邊緣或中心點貼齊指定位置,注意,不能同時使用「top 與 bottom」或「left 與 right」。
關鍵字 等同屬性值 說明 top center top
靠上對齊 right right center
靠右對齊 bottom center bottom
靠下對齊 left left center
靠左對齊 center center center
置中對齊 left top - 靠左上對齊 ( 預設值 ) left bottom - 靠左下對齊 right top - 靠右上對齊 right bottom - 靠右下對齊 位置偏移量 ( 百分比 )
使用百分比單位,在沒有設定對齊關鍵字的狀態下,採用「
left top
」的方式進行偏移,並按照「百分比公式」計算偏移量,由於最終偏移結果是按照公式計算出的數值,如果背景圖尺寸大於元素尺寸,計算後會往反向移動 ( 類似設定負值的 px ),如果遮罩圖片尺寸小於元素尺寸,計算後會順向移動,這個寫法會有「1~2」個屬性值。( 容器寬度 - 遮罩圖片寬度 ) * x 偏移百分比 = x 方向偏移量 ( 容器高度 - 遮罩圖片高度 ) * y 偏移百分比 = y 方向偏移量
屬性值 等同屬性值 ( top left ) 說明 50%
50% 50%
左往右偏移 50%,上往下偏移 50% 50% 100%
- 左往右偏移 50%,上往下偏移 100% 位置偏移量 ( px、em、rem )
使用非百分比的長度單位,在沒有設定對齊關鍵字的狀態下,採用「
left top
」的方式進行偏移,px 表示像素,em 表示元素本身字型大小,rem 表示根元素字型大小,設定負值會往反方向移動,這個寫法會有「1~2」個屬性值。屬性值 等同屬性值 ( top left ) 說明 50px
50px 50px
左往右偏移 50px,上往下偏移 50px 50px 100px
- 左往右偏移 50px,上往下偏移 100px 混合對齊關鍵字與位置偏移量
將「對齊關鍵字」和「位置偏移量」組合,就能指定「哪個方向的偏移量」,這個寫法會有「4」個屬性值,注意,不支援使用 center 位置關鍵字。
屬性值 等同屬性值 說明 right 20% bottom 20%
-20% -20% 右往左偏移 20%,下往上偏移 20% left 20% top 20%
20% 20% 右往左偏移 20%,上往下偏移 20%
下列範例會讓不同的 div 呈現不同的 mask-position
遮罩效果。
<!-- HTML 程式碼-->
<div class="a"></div>
<div class="b"></div>
<div class="c"></div>
<div class="d"></div>
<div class="e"></div>
<div class="f"></div>
<!-- CSS 程式碼 -->
<style>
div {
width:300px;
height: 150px;
margin: 20px;
background: url('https://steam.oxxostudio.tw/image/index-css.jpg');
mask-image: url('https://steam.oxxostudio.tw/download/css/mask-demo-03.svg');
mask-repeat: no-repeat;
mask-size: 200px;
}
.a {mask-position: center center;} /* 水平置中,垂直置中 */
.b {mask-position: 0% 0%;} /* 靠左靠上對齊,偏移 0% */
.c {mask-position: right bottom;} /* 靠右靠下對齊 */
.d {mask-position: 20px 50px;} /* 靠左靠上對齊,往右移動 20px,往下移動 50px */
.e {mask-position: right 20px bottom 50px;} /* 靠右靠下對齊,往左移動 20px,往上移動 50px */
.f {mask-position: left 20px top 50px;} /* 靠左靠上對齊,往右移動 20px,往下移動 50px */
</style>
mask-size 遮罩尺寸
mask-size
可以設定「遮罩尺寸」,使用方式和 background-size
完全相同,使用「尺寸關鍵字」或「尺寸數值」的屬性值來定義遮罩圖片的尺寸,沒有繼承特性,由於 mask-size
主要針對「具有長寬尺寸或比例」的圖片計算出遮罩圖片的長寬,因此如果使用的圖片沒有長寬尺寸或比例 ( 例如漸層色、部分特殊設定的 SVG ),就不會套用遮罩圖片尺寸樣式。
注意,
mask-size
一定要放在mask-image
和mask-position
後方才會正常顯示。
下方列出屬性值的說明:
屬性值 | 類型 | 說明 |
---|---|---|
cover | 關鍵字 | 維持圖片比例,將寬度或高度縮放至元素「最大邊長」( 無法和數值搭配 )。 |
contain | 關鍵字 | 維持圖片比例,將寬度或高度縮放至元素「最小邊長」」( 無法和數值搭配 )。 |
auto | 關鍵字 | 維持圖片比例,根據寬調整高,或根據高調整寬,沒有設定寬高就使用圖片原始尺寸。 |
N% | 數值 | 寬 = 元素寬 x N%,高 = 元素高 x N%。 |
X% Y% | 數值 | 寬 = 元素寬 x X%,高 = 元素高 x Y%。 |
Npx | 數值 | 寬 = Npx,高 = Npx。 |
Xpx Ypx | 像數值 | 寬 = Xpx,高 = Ypx。 |
em | 數值 | 使用元素字型大小,算法等同 px 或 % |
rem | 數值 | 使用根元素字型大小,算法等同 px 或 % |
使用 mask-size
時,只有 auto 關鍵字可以和數值共同使用,產生 1~2 個屬性值,如果 auto 寫在數值左方表示寬度等比例調整,auto 寫在數值右方表示高度等比例調整,下方範例會用不同的屬性值,呈現不同的 mask-size
屬性值的效果。
<!-- HTML 程式碼-->
<div class="a"></div>
<div class="b"></div>
<div class="c"></div>
<div class="d"></div>
<div class="e"></div>
<div class="f"></div>
<!-- CSS 程式碼 -->
<style>
div {
width:300px;
height: 150px;
margin: 20px;
background: url('https://steam.oxxostudio.tw/image/index-css.jpg');
mask-image: url('https://steam.oxxostudio.tw/download/css/mask-demo-01.png');
}
.a {mask-size: cover;} /* 填滿最大邊長 */
.b {mask-size: contain;} /* 填滿最小邊長 */
.c {mask-size: auto 40%;} /* 寬度等比例,高度 = 元素高 x 40% */
.d {mask-size: 40%;} /* 寬度 = 元素寬 x 40%,高度 = 元素高 x 40% */
.e {mask-size: 80% 20px;} /* 寬度 = 元素寬 x 80%,高度 = 20px */
.f {mask-size: 30px 200px;} /* 寬度 = 30px,高度 = 200px */
</style>
mask-origin 遮罩參照
mask-origin
表示遮罩「參照容器盒子模型」而產生的「範圍」,參考「容器盒子模型 (Box Model )」教學內容,mask-origin
具有下列屬性值:
屬性值 | 說明 |
---|---|
border-box | 遮罩範圍包含邊框寬度。 |
padding-box | 遮罩範圍包含內邊距寬度。 |
content-box | 遮罩範圍只有內容尺寸。 |
下方範例會呈現不同的 mask-origin
遮罩範圍所呈現的效果,遮罩縮放效果會因為範圍不同而有所不同,可以注意範例中垂直遮罩線條的粗細不同。
<!-- HTML 程式碼-->
<div class="a"></div>
<div class="b"></div>
<div class="c"></div>
<!-- CSS 程式碼 -->
<style>
div {
margin: 30px;
padding: 20px;
border: 20px solid red;
width: 200px;
height: 100px;
background: url('https://steam.oxxostudio.tw/image/index-css.jpg');
mask-image: repeating-linear-gradient(
to right,
#0006 0%, #0006 5%,
#000f 5%, #000f 10%
);
mask-size: contain;
mask-position: center;
mask-repeat: no-repeat;
}
.a {mask-origin: content-box;}
.b {mask-origin: padding-box;}
.c {mask-origin: border-box;}
</style>
mask-clip 遮罩裁切
mask-clip
表示「參考容器盒子模型」而「裁切」後的遮罩,有點類似 mask-origin
,參考「容器盒子模型 (Box Model )」教學內容,mask-clip
具有下列屬性值:
屬性值 | 說明 |
---|---|
border-box | 遮罩裁切範圍包含邊框寬度。 |
padding-box | 遮罩裁切範圍包含內邊距寬度。 |
content-box | 遮罩裁切範圍只有內容尺寸。 |
下方範例會呈現不同的 mask-clip
遮罩範圍所呈現的效果。
<!-- HTML 程式碼-->
<div class="a"></div>
<div class="b"></div>
<div class="c"></div>
<!-- CSS 程式碼 -->
<style>
div {
margin: 30px;
padding: 20px;
border: 20px solid red;
width: 200px;
height: 100px;
background: url('https://steam.oxxostudio.tw/image/index-css.jpg');
mask-image: url('https://steam.oxxostudio.tw/download/css/mask-demo-03.svg');
mask-size: contain;
mask-position: center;
mask-repeat: no-repeat;
}
.a {mask-clip: content-box;}
.b {mask-clip: padding-box;}
.c {mask-clip: border-box;}
</style>
mask-composite 遮罩集合運算
mask-composite
表示多重遮罩之間的「集合」,根據不同的集合方式,會產生不同的效果,下方列出支援的集合方式:
集合方式 | 說明 |
---|---|
add | 聯集,所有遮罩圖形都是遮罩範圍。 |
subtract | 差集,前方遮罩會移除和後方遮罩的重疊範圍。 |
intersect | 交集,保留遮罩重疊的部分。 |
exclude | 對稱差集,移除重疊的部分。 |
下方會使用垂直和水平兩種漸層條紋,搭配九宮格的背景,清楚呈現這些集合方式的差異。
<!-- HTML 程式碼-->
<div class="a"></div>
<div class="b"></div>
<div class="c"></div>
<div class="d"></div>
<!-- CSS 程式碼 -->
<style>
div {
margin: 30px;
width: 200px;
height: 200px;
background: url('https://steam.oxxostudio.tw/download/css/border-img-2.jpg');
background-size: cover;
mask-image: repeating-linear-gradient(
to right,
#000f 0%, #000f 33.33%,
#0000 33.33%, #0000 66.66%
),repeating-linear-gradient(
to bottom,
#000f 0%, #000f 33.33%,
#0000 33.33%, #0000 66.66%
);
mask-size: cover;
}
.a {mask-composite: add;}
.b {mask-composite: subtract;}
.c {mask-composite: intersect;}
.d {mask-composite: exclude;}
</style>
mask 遮罩縮寫樣式
元素套用遮罩時,為了避免 CSS 程式碼過於冗長,有時會使用縮寫的 mask
樣式屬性,這個樣式沒有繼承特性,需要注意下列的幾個事項:
mask-size
一定要接在mask-position
之後且使用「/
」分隔,若只有長度數值則表示mask-position
屬性值。- 出現
mask-origin
和mask-clip
相關屬性值時,如果只有一個就是mask-origin
,出現的第二個是mask-clip
。- 使用
mask
可能會覆蓋掉對應的遮罩樣式,反之其他遮罩樣式也可能會覆蓋mask
裡對應的樣式。- 如果有多重遮罩,使用「逗號」分隔多個遮罩樣式。
下方列出一些符合規範的 mask
寫法:
div {
mask: url(...);
/* 等同 */
/* mask-image: url(...) */
mask: url(...) luminance;
/* 等同 */
/* mask-image: url(...); */
/* mask-mode: luminance; */
mask: url(...) luminance 20% 30%;
/* 等同 */
/* mask-image: url(...); */
/* mask-mode: luminance; */
/* mask-position: 20% 30%; */
mask: url(...) luminance 20% 30% / 50%;
/* 等同 */
/* mask-image: url(...); */
/* mask-mode: luminance; */
/* mask-position: 20% 30%; */
/* mask-size: 50%; */
background: url(...) luminance 20% 30% / 50% padding-box;
/* 等同 */
/* mask-image: url(...); */
/* mask-mode: luminance; */
/* mask-position: 20% 30%; */
/* mask-size: 50%; */
/* mask-origin: padding-box */
background: url(...) luminance 20% 30% / 50% padding-box padding-box;
/* 等同 */
/* mask-image: url(...); */
/* mask-mode: luminance; */
/* mask-position: 20% 30%; */
/* mask-size: 50%; */
/* mask-origin: padding-box */
/* mask-clip: padding-box */
}
下方範例會使用 mask
縮寫樣式表現影像遮罩。
<!-- HTML 程式碼-->
<div></div>
<div></div>
<!-- CSS 程式碼 -->
<style>
div {
position: absolute;
top: 10px;
left: 10px;
width: 600px;
height: 320px;
}
div:nth-child(1) {
background: url('https://steam.oxxostudio.tw/image/index-css.jpg') center / cover;
opacity: 0.6;
}
div:nth-child(2) {
width: 600px;
height: 320px;
background: url('https://steam.oxxostudio.tw/image/index-css.jpg') center / cover;
mask: url('https://steam.oxxostudio.tw/download/css/mask-demo-01.png') center / 15% space;
}
</style>
小結
透過 mask
可以輕鬆實現網頁的簡單特效,雖然過去的瀏覽器對於這個樣式的支援度不高,但隨著科技的進步,目前大部分瀏覽器都已經支援,也可以開始使用這個樣式屬性,做出各種有趣的遮罩效果!
意見回饋
如果有任何建議或問題,可傳送「意見表單」給我,謝謝~