mask:巧用遮罩解决各类视觉难题
本章节主要介绍 mask 属性,通过 mask 属性可以解决一些视觉上的难题,比如裁剪、内切圆等。mask 还能使用 background 的属性实现渐变效果,如显隐、融合等。mask-composite 属性还能设置遮罩的叠加效果。
mask 属性介绍
mask 属性是CSS3新增的属性,用于设置元素的遮罩层,通过遮罩层可以控制元素的哪些部分是可见的,哪些部分是不可见的。
mask 可以接受一个与 background 一样的参数,那就是渐变,语法如下:
mask: linear-gradient(rgba(0, 0, 0, 0.5), transparent);它的作用可以通过一个例子来说明:
<div class="mask"></div>.mask {
width: 200px;
height: 200px;
background: url(./img.jpg);
mask: linear-gradient(rgba(0, 0, 0, 0.5), transparent);
}
mask 允许使用者通过遮罩的方式隐藏一个元素的部分区域。只要元素的内容与 mask 生成的渐变透明部分重叠,就会变得透明。
因此,mask 属性有一些黑科技技巧来实现一些视觉上的效果。
技巧一:用 mask 实现裁剪
在 渐变可以叠加多层 中介绍了渐变可以叠加多层,且 mask 属性也可以使用 background 的渐变属性,就可以使用这个技巧实现图片的裁剪。
<div class="clip"></div>.clip {
width: 200px;
height: 100px;
background: url(./img.jpg);
mask: linear-gradient(45deg, transparent 20px, skyblue 0) bottom left, linear-gradient(
-45deg,
transparent 20px,
skyblue 0
) bottom right,
linear-gradient(-135deg, transparent 20px, skyblue 0) top right, linear-gradient(
135deg,
transparent 20px,
skyblue 0
) top left;
mask-repeat: no-repeat;
mask-size: 50% 50%;
}最终得到的效果图如下:

同理,还能使用 mask 实现内切圆效果。
div {
background: radial-gradient(
circle at 100% 100%,
transparent 0,
transparent 12px,
#2179f5 13px
), radial-gradient(
circle at 0 0,
transparent 0,
transparent 12px,
#2179f5 13px
), radial-gradient(
circle at 100% 0,
transparent 0,
transparent 12px,
#2179f5 13px
), radial-gradient(circle at 0 100%, transparent 0, transparent 12px, #2179f5
13px);
background-repeat: no-repeat;
background-position: right bottom, left top, right top, left bottom;
background-size: 50% 50%;
}把之前内切角的例子修改一下,把线性渐变修改为径向渐变,圆心修改为四个角,得到以下的效果:

效果实现得不错,但这是基于背景是纯色的情况。如果背景要求渐变色,上述方案是无法完成的。而 mask 属性可以轻松完成这个需求,只需要把上方代码中的 background 属性修改为 mask 属性即可,background 设置自己的线性渐变色。
div {
background: linear-gradient(45deg, #2179f5, #e91e63);
background: radial-gradient(
mask: radial-gradient(
circle at 100% 100%,
transparent 0,
transparent 12px,
#2179f5 13px
), radial-gradient(
circle at 0 0,
transparent 0,
transparent 12px,
#2179f5 13px
), radial-gradient(
circle at 100% 0,
transparent 0,
transparent 12px,
#2179f5 13px
), radial-gradient(circle at 0 100%, transparent 0, transparent 12px, #2179f5
13px);
background-repeat: no-repeat;
background-position: right bottom, left top, right top, left bottom;
background-size: 50% 50%;
mask-repeat: no-repeat;
mask-position: right bottom, left top, right top, left bottom;
mask-size: 70% 70%;
}具体效果可以查看 mask 实现内切圆。
原理如下图所示,和之前一样,重叠部分如果是透明的,元素也会变得透明不显示:

技巧二:用 mask 实现渐变显隐
在 渐变颜色可以设置透明色 中,利用伪类设置线性渐变让末尾透明来实现渐隐,现在可以利用 mask 属性来实现渐隐效果。
div {
ul {
display: flex;
align-items: center;
flex-wrap: nowrap;
width: 200px;
overflow-x: scroll;
mask: linear-gradient(90deg, transparent, #fff);
}
}技巧三:用 mask 实现融合效果
来看一个效果:

这两个图片叠加在一起,实现方式也很简单,为 div 绑定背景图片,然后通过伪类 ::before 也绑定另一个背景图,设置 mask 属性,线性渐变角度为 45deg ,渐变颜色从随意颜色到透明色,中间过渡用实色过渡。
div {
width: 200px;
height: 200px;
background: url(./img1.jpg);
position: relative;
&::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: url(./img2.jpg);
mask: linear-gradient(45deg, #2179f5 50%, transparent 50%);
}
}如果想要用到不透明到透明的平滑渐变过渡,在渐变中修改一下颜色的范围百分比即可。
div {
width: 200px;
height: 200px;
background: url(./img1.jpg);
position: relative;
&::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: url(./img2.jpg);
mask: linear-gradient(45deg, #2179f5 50%, transparent 50%);
mask: linear-gradient(45deg, #2179f5 40%, transparent 60%);
}
}技巧四:用 mask 实现内容切换效果
几个技巧可以看出 mask 这个属性的强大,mask 主要的作用是遮罩,遮住部分甚至全部的内容,因此发散思维,还能通过 mask 实现内容切换效果。
主要的实现思路为,父 div 使用背景图片一,子 div 使用背景图片二,宽高一样,子图片 mask-size 宽设置为两倍,mask 设置前 50% 可显示,后 50% 透明。动画修改 mask-position 的值,把前 50% 可显示的部分显示子图。
<div class="g-outer">
<div class="g-inner"></div>
</div>div {
width: 200px;
height: 100px;
}
.g-outer {
background: url(https://picsum.photos/200/100.jpg?random=1) no-repeat center /
100%;
}
.g-inner {
background: url(https://picsum.photos/200/100.jpg?random=2) no-repeat center /
100%;
mask: linear-gradient(
90deg,
#fff 0%,
#fff 50%,
transparent 50%,
transparent 100%
);
mask-size: 200% 100%;
animation: maskChange 2s infinite alternate linear;
}
@keyframes maskChange {
0% {
mask-position: -100% 0;
}
100% {
mask-position: 0 0;
}
}具体效果可以查看 mask 实现内容切换效果。
技巧五:mask-composite 组合遮罩大法,让切图更轻松
mask 家族还有一个特别好用的属性 mask-composite ,这个属性可以设置遮罩的叠加方式。通俗来讲,如果有多个 mask 重叠,它能们按照一定的规则进行叠加。
看起来还是很抽象,没关系,可以根据一个例子来理解。

上图需要实现一个圆形的遮罩,代码很简单,通过 mask 属性设置 mask: radial-gradient(circle at 0 0, #000 50%, transparent 50.3%); 即可。
div {
width: 100px;
height: 100px;
background: #000;
mask: radial-gradient(circle at 0 0, #000 50%, transparent 50.3%);
}
反过来也同样适用,只需要把径向渐变的圆心从左上角修改为右上角即可。
div {
width: 100px;
height: 100px;
background: #000;
mask: radial-gradient(circle at 100% 0, #000 50%, transparent 50.3%);
}如果想要实现更高级的效果:

直接 mask 堆叠即可:修改代码看看效果。
div {
width: 100px;
height: 100px;
background: #000;
mask: radial-gradient(circle at 0 0, #000 50%, transparent 50.3%),
radial-gradient(circle at 100% 0, #000 50%, transparent 50.3%);
}
效果并不是我们想象的效果。因为 mask 默认只是堆叠,正常堆叠就是上方代码的效果,因此没啥问题。而最终想要的效果是堆叠的重合部分,因此需要用到 mask-composite 属性,这个属性可以设置遮罩的叠加方式,默认值为 add ,表示堆叠,而取重叠部分需要设置 -webkit-mask-composite: source-in; 。
div {
width: 100px;
height: 100px;
background: #000;
mask: radial-gradient(circle at 0 0, #000 50%, transparent 50.3%),
radial-gradient(circle at 100% 0, #000 50%, transparent 50.3%);
-webkit-mask-composite: source-in;
}具体效果可以查看 mask-composite 组合遮罩。
mask-composite 属性目前的标准规范只支持四个模式:
mask-composite: add; // 默认值,堆叠
mask-composite: subtract; // 堆叠重合部分取反
mask-composite: intersect; // 只要堆叠重合部分
mask-composite: exclude; // 排除堆叠重合部分一图流方便理解:

还有一些属性需要借助 -webkit- 前缀,因此兼容性不是很好,只是语法略有不同。
-webkit-mask-composite: clear; /*清除,不显示任何遮罩*/
-webkit-mask-composite: copy; /*只显示上方遮罩,不显示下方遮罩*/
-webkit-mask-composite: source-over;
-webkit-mask-composite: source-in; /*只显示重合的地方*/
-webkit-mask-composite: source-out; /*只显示上方遮罩,重合的地方不显示*/
-webkit-mask-composite: source-atop;
-webkit-mask-composite: destination-over;
-webkit-mask-composite: destination-in; /*只显示重合的地方*/
-webkit-mask-composite: destination-out; /*只显示下方遮罩,重合的地方不显示*/
-webkit-mask-composite: destination-atop;
-webkit-mask-composite: xor; /*只显示不重合的地方*/总结
mask 属性是一个非常有用的属性,可以用来实现很多有意思的效果,比如图片的裁剪、透明度、内容切换等。当然,mask 属性的兼容性不是很好,因此在使用的时候,需要考虑一下兼容性问题。
在多个 mask 属性堆叠的时候,可以使用 mask-composite 属性来设置遮罩的叠加方式,从而实现更丰富的效果。