跳转到内容

mask:巧用遮罩解决各类视觉难题

本章节主要介绍 mask 属性,通过 mask 属性可以解决一些视觉上的难题,比如裁剪、内切圆等。mask 还能使用 background 的属性实现渐变效果,如显隐、融合等。mask-composite 属性还能设置遮罩的叠加效果。

mask 属性介绍

mask 属性是CSS3新增的属性,用于设置元素的遮罩层,通过遮罩层可以控制元素的哪些部分是可见的,哪些部分是不可见的。

mask 可以接受一个与 background 一样的参数,那就是渐变,语法如下:

css
mask: linear-gradient(rgba(0, 0, 0, 0.5), transparent);

它的作用可以通过一个例子来说明:

html
<div class="mask"></div>
css
.mask {
  width: 200px;
  height: 200px;
  background: url(./img.jpg);
  mask: linear-gradient(rgba(0, 0, 0, 0.5), transparent);
}

mask 效果

mask 允许使用者通过遮罩的方式隐藏一个元素的部分区域。只要元素的内容与 mask 生成的渐变透明部分重叠,就会变得透明。

因此,mask 属性有一些黑科技技巧来实现一些视觉上的效果。

技巧一:用 mask 实现裁剪

渐变可以叠加多层 中介绍了渐变可以叠加多层,且 mask 属性也可以使用 background 的渐变属性,就可以使用这个技巧实现图片的裁剪。

html
<div class="clip"></div>
css
.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 实现内切圆效果。

css
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 设置自己的线性渐变色。

css
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 属性来实现渐隐效果。

less
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 ,渐变颜色从随意颜色到透明色,中间过渡用实色过渡。

less
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%);
  }
}

如果想要用到不透明到透明的平滑渐变过渡,在渐变中修改一下颜色的范围百分比即可。

less
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% 可显示的部分显示子图。

html
<div class="g-outer">
  <div class="g-inner"></div>
</div>
less
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%); 即可。

css
div {
  width: 100px;
  height: 100px;
  background: #000;
  mask: radial-gradient(circle at 0 0, #000 50%, transparent 50.3%);
}

圆形遮罩反向

反过来也同样适用,只需要把径向渐变的圆心从左上角修改为右上角即可。

css
div {
  width: 100px;
  height: 100px;
  background: #000;
  mask: radial-gradient(circle at 100% 0, #000 50%, transparent 50.3%);
}

如果想要实现更高级的效果:

圆形遮罩组合

直接 mask 堆叠即可:修改代码看看效果。

css
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;

css
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 属性目前的标准规范只支持四个模式:

css
mask-composite: add; // 默认值,堆叠
mask-composite: subtract; // 堆叠重合部分取反
mask-composite: intersect; // 只要堆叠重合部分
mask-composite: exclude; // 排除堆叠重合部分

一图流方便理解:

mask-composite一图流

还有一些属性需要借助 -webkit- 前缀,因此兼容性不是很好,只是语法略有不同。

css
-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 属性来设置遮罩的叠加方式,从而实现更丰富的效果。

贡献者

The avatar of contributor named as 刀刀 刀刀
The avatar of contributor named as duyidao duyidao

页面历史

刀刀博客累计访客 人;文档累计访问量共