https://www.zhangxinxu.com/wordpress/2017/11/css-css3-mask-masks/ 张已经有过相同的文件
在过去,CSSmask属性在使用的时候就是mask: xxx,但是现在随着这个属性的规范化,mask属性实际上已经成为了诸多mask-*的缩写,这和background,border性质是一样的。
具体是哪些属性的缩写呢,可以参见下面的列表:
下面对上面的这些属性,一个一个介绍。
一 CSS mask-image
mask-image指遮罩使用的图片资源,默认值是none,也就是无遮罩图片。因此,和border属性中的border-style属性类似,是一个想要有效果就必须设定的属性值。
mask-image遮罩所支持的图片类型非常的广泛,可以是url()静态图片资源,格式包括JPG,PNG以及SVG等都是支持的;也可以是动态生成的图片,例如使用各种CSS3渐变绘制的图片。语法上支持CSS3各类渐变,以及url()功能符,image()功能符,甚至element()功能符。同时还支持多背景,因此理论上,使用mask-image我们可以遮罩出任意我们想要的图形,非常强大。
眼见为实,我们通过大量案例来展示mask-image的强大之处。
1. 最基础的png图片遮罩展示
我们使用的遮罩图片是一个名为loading.png的图片,如下:
<img src="ps1.jpg" class="mask-image">
.mask-image {
width: 250px; height: 187.5px;
-webkit-mask-image: url(loading.png);
mask-image: url(loading.png);
}
最后的效果,如下图所示:
从上面这个最基本的案例,我们可以看出,所谓遮罩,就是原始图片只显示遮罩图片非透明的部分。例如本案例中,loading圆环有颜色部分就是外面一圈圆环,于是最终我们看到效果是原始图片,只露出了一个一个的圈圈环。并且半透明区域也准确遮罩显示了。
因此,我们很少使用jpg图片来作为遮罩图片的,因为jpg图片一定是完全不透明的,最终的效果就是原图什么也看不到。
2. SVG图形遮罩效果展示
除了支持普通静态图片的遮罩,mask-image还支持SVG图形的遮罩效果。
假设有下面名为star.svg的SVG图形:
CSS代码如下:
.mask-image {
width: 250px; height: 187.5px;
-webkit-mask-image: url(star.svg);
mask-image: url(star.svg);
}
3. SVG图形中元素作为遮罩
此用法和上面的区别在于仅仅是使用SVG中定义的
在定义上,我们既能够把内联SVG中的
单从最终的表现上来看,内联使用还是外链使用,应用在普通HTML上和应用在SVG原生上是有比较大的兼容性差异的,这里有必要好好说明下。
假设有如下SVG代码:
<svg width="50" height="50" version="1.1" xmlns="http://www.w3.org/2000/svg">
<ellipse cx="25" cy="25" rx="20" ry="10" fill="#000000" stroke="none"></ellipse>
<rect x="15" y="5" width="20" height="40" rx="5" ry="5" fill="#000000" stroke="none"></rect>
</svg>
理论上,我们外面直接套个
<svg>
<defs>
<mask id="mask">
<ellipse cx="25" ...></ellipse>
<rect x="15" ...></rect>
</mask>
</defs>
</svg>
但是,注意,如果作为CSSmask属性值使用,上面这样直接处理是没有任何效果的,主要问题在于尺寸的识别上会有障碍。
通常的做法是设定
于是,本案例需要的SVG
<svg>
<defs>
<mask id="mask" maskContentUnits="objectBoundingBox">
<ellipse cx=".5" cy=".5" rx=".4" ry=".2" fill="white"></ellipse>
<rect x=".3" y=".1" width=".4" height=".8" rx=".1" ry=".1" fill="white"></rect>
</mask>
</defs>
</svg>
事情并没有那么简单
SVG
其遮罩模式默认和普通图片的遮罩是不一样的,其遮罩类型是luminance,也就是基于亮度来进行遮罩的。而普通图片默认遮罩类型是alpha,基于透明度来遮罩的。当然,我们可以通过mask-type或mask-mode来设置SVG 遮罩类型是alpha,用法为:mask-type:alpha。因此,上面代码两个形状的填充使用的是fill=”white”,白色亮度最高,表示完全遮罩。如果换成fill=”black”则是完全透明。 假设上面的SVG代码内联在页面中,同时我们应用了如下CSS代码:.mask-image {
mask-image: url(#mask); / #mask对应SVG中元素的id属性值 /
}结果会发现,在Firefox浏览器下(目前仅Firefox浏览器支持任意元素的SVG遮罩),遮罩效果的边缘有些毛糙:
显然这样的遮罩效果是无法让我们满意的,好在我们是有办法可以让这个边缘变得更加平滑的,那就是重新构建一套同样形状,尺寸略大的,填充为黑色的图形,类似下面:
<svg>
<defs>
<mask id="mask" maskContentUnits="objectBoundingBox">
<!-- 柔化边缘 -->
<ellipse cx=".5" cy=".5" rx=".48" ry=".28" fill="black"></ellipse>
<rect x=".2" y="0" width=".6" height="1" rx=".1" ry=".1" fill="black"></rect>
<!-- 主体遮罩 -->
<ellipse cx=".5" cy=".5" rx=".4" ry=".2" fill="white"></ellipse>
<rect x=".3" y=".1" width=".4" height=".8" rx=".1" ry=".1" fill="white"></rect>
</mask>
</defs>
</svg>
此时,我们的图片遮罩边缘就变得异常平滑了,如下截图
- 当包含
遮罩的SVG内联在页面中的时候,我们是不希望这个SVG占据任何尺寸的,需要把这个SVG隐藏掉。此时,是不能使用display:none或者使用visibility:hidden隐藏的,否则我们的遮罩效果就会失效。需要使用其他的方法隐藏,例如: ```javascript svg { width: 0; height: 0; position: absolute; } // 或者(-150px仅示意不具代表性)
svg { position: absolute; left: -150px; top: -150px; }
<a name="cgmm0"></a>
#### 4 不同调用方式和作用的不同元素上的兼容
SVG代码都是上面带“柔化边缘”注释的那段代码:
1. **普通HTML元素内联SVG的<mask>**
HTML和CSS代码如下:
```javascript
<img src="ps1.jpg" class="mask-image"> // html
.mask-image { // css
width: 250px; height: 187.5px;
-webkit-mask-image: url(#mask);
mask-image: url(#mask);
}
结果显示Chrome浏览器并不支持:
Firefox浏览器表现符合预期:
- SVG元素内联SVG的
<svg width="250" height="186">
<image xlink:href="ps1.jpg" class="mask-image" width="250" height="186"></image>
</svg>
.mask-image {
width: 250px; height: 187.5px;
-webkit-mask-image: url(#mask);
mask: url(#mask);
mask-image: url(#mask);
}
结果所有浏览器,包括IE9浏览器都表现为预期的“姨妈巾”遮罩效果:
包括IE9在内浏览器全部遮罩有效,并不是因为支持mask-image属性,除了Firefox浏览器,实际上目前其他所有浏览器都不支持SVG元素的元素上设置mask属性,类似这样:
<svg width="250" height="186">
<image xlink:href="ps1.jpg" mask="url(#mask)" width="250" height="186"></image>
</svg>
因此,才有效果的。类似的CSS中的fill,stroke可以作用在SVG元素也是同样道理。
而mask-image是CSS特有,SVG本身并没有,因此,如果是下面CSS:
.mask-image {
width: 250px; height: 187.5px;
-webkit-mask-image: url(#mask);
mask-image: url(#mask);
}
则同样是仅Firefox浏览器支持。
3 普通HTML元素外链SVG文件的
无论是clip-path还是这里的mask,外链SVG特性的支持一定是比内联SVG弱的。既然Chrome浏览器连普通HTML的内联SVG的
那之前表现良好的Firefox浏览器呢?
比较幸运,Firefox浏览器最近支持了任意元素外链SVG文件的
5. 渐变作为遮罩图片
这里的渐变可以是任意类型的CSS3渐变,例如可以是linear-gradient()线性渐变,也可以是repeating-linear-gradient()重复线性渐变,也可以是radial-gradient()径向渐变,也可以是repeating-radial-gradient()重复径向渐变,也可以是conic-gradient锥形渐变(只要浏览器支持)。
例如下面的CSS代码:
.mask-image {
width: 250px; height: 187.5px;
-webkit-mask-image: repeating-radial-gradient(rgba(0,0,0,0) 4px, rgba(0,0,0,1) 10px, rgba(0,0,0,1) 12px);
mask-image: repeating-radial-gradient(rgba(0,0,0,0) 4px, rgba(0,0,0,1) 10px, rgba(0,0,0,1) 12px);
}
四、CSS mask-mode属性详细介绍
mask-mode属性的默认值是match-source,意思是根据资源的类型自动采用合适的遮罩模式。
例如,如果我们的遮罩使用的是SVG中的
因此,mask-mode支持下面3个属性值:
mask-mode: alpha;
mask-mode: luminance;
mask-mode: match-source;
因为mask-image支持多图片,因此mask-mode也支持多属性值,例如:
mask-mode: alpha, match-source;
例如,我们把loading.png遮罩改成基于亮度luminance,如下CSS:
.mask-image {
width: 250px; height: 187.5px;
-webkit-mask-image: url(loading.png);
mask-image: url(loading.png);
-webkit-mask-mode: luminance;
mask-mode: luminance;
}
结果Firefox浏览器下:
目前,mask-mode仅Firefox浏览器支持,因此,Chrome浏览器是看到的依然是基于alpha遮罩的效果,颜色不像上图那样淡。
眼见为实,您可以狠狠地点击这里:mask-mode:luminance与png图片遮罩demo
五、mask-repeat属性详细介绍
mask-repeat属性的默认值是repeat,行为类似于background-repeat属性。
支持以下一些单属性值:
mask-repeat: repeat-x;
mask-repeat: repeat-y;
mask-repeat: repeat;
mask-repeat: no-repeat;
mask-repeat: space;
mask-repeat: round;
同时,根据自己的测试,Chrome和Firefox浏览器都支持x轴y轴2两轴同时表示,例如:
mask-repeat: repeat space;
mask-repeat: repeat repeat;
mask-repeat: round space;
mask-repeat: no-repeat round;
由于mask-image支持多遮罩图片,因此,mask-repeat也支持多属性值,例如:
mask-repeat: space round, no-repeat;
mask-repeat: round repeat, space, repeat-x;
每个属性值的含义如下:
repeat-x
水平x平铺,效果类似:
repeat-y
垂直y平铺。
repeat
默认值,水平和垂直平铺。
no-repeat
不平铺,会看到就一个遮罩图形孤零零的挂在左上角。
space
space同background等属性中的space,表示遮罩图片尽可能的平铺同时不发生任何剪裁。
然而根据我的测试,在Chrome浏览器下,一侧边缘还是发生了剪裁,不过不明显。Firefox浏览器则完美表现。
round
round表示遮罩图片尽可能靠在一起没有任何间隙,同时不发生任何剪裁。这就意味着图片可能会有比例的缩放。
关于每个属性值的具体表现,我特意做了一个demo,您可以狠狠的点击这里:mask-repeat不同属性值与遮罩效果demo
例如我们选择mask-repeat为round,则遮罩效果就变成这样:
六、mask-position属性详细介绍
mask-position和background-position支持的属性值和表现基本上都是一模一样的。
例如,mask-position默认计算值是0% 0%,也就是相对左上角定位。
支持单个关键字(缺省关键字的解析为center):
mask-position: top;
mask-position: bottom;
mask-position: left;
mask-position: right;
mask-position: center;
支持垂直和水平方向两个关键字:
mask-position: right top;
支持各类数值:
mask-position: 30% 50%;<
mask-position: 10px 5rem;
由于mask-image支持多遮罩图片,因此,mask-position也支持多属性值,例如:
mask-position: 0 0, center;
Chrome和Firefox浏览器都支持mask-position属性,Chrome还需要-webkit-私有前缀,Firefox浏览器现在已经不需要了。
为了直观体验不同mask-position属性值的遮罩效果,我特意做了个可交互的demo页面,您可以狠狠的点击这里:mask-position不同属性值与遮罩效果demo
例如,在mask-repeat值为no-repeat前提下,我们选择属性值为top,则遮罩效果表现为顶部居中:
七、mask-clip属性详细介绍
mask-clip属性性质上和background-clip类似,但是mask-clip支持的属性值要多一点,主要是多了个SVG元素的mask-clip支持。
支持属性值如下:
mask-clip: content-box;
mask-clip: padding-box;
mask-clip: border-box;
mask-clip: fill-box;
mask-clip: stroke-box;
mask-clip: view-box;
mask-clip: no-clip;
其中默认值是border-box和background-clip类似。同样也支持多属性值:
mask-clip: content-box, border-box;
虽然支持的属性值挺多,但是对于普通元素而言,生效的其实就前面3个,Firefox浏览器还支持no-clip,表示不对元素的遮罩效果做区域上的限制,言外之意就是只要是元素身上“长出来”的东西,都可以应用遮罩效果。
例如outline轮廓,又例如box-shadow盒阴影,都是可以应用遮罩效果的。
做了个demo,演示不同mask-clip属性值的不同表现,您可以狠狠的点击这里:mask-clip不同属性值与遮罩效果demo
例如,已知CSS如下:
.mask-image {
width: 250px; height: 187.5px;
-webkit-mask-image: url(loading.png);
mask-image: url(loading.png);
border: 20px solid #34538b;
padding: 20px;
margin: 20px;
}
则我们选择content-box效果:
fill-box,stroke-box,view-box要与SVG元素关联才有效果,目前还没有任何浏览器对其进行支持更新于2020-07-26 Firefox浏览器支持了这3个关键字,反而是Chrome浏览器迟迟未支持。
八、mask-origin属性详细介绍
mask-origin属性性质上和background-origin类似,但是mask-origin支持的属性值要多一点,主要是多了个SVG元素的mask-origin支持。
支持属性值如下:
mask-origin: content-box;
mask-origin: padding-box;
mask-origin: border-box;
mask-origin: fill-box;
mask-origin: stroke-box;
mask-origin: view-box;
其中默认值是border-box和background-origin类似。同样也支持多属性值:
mask-origin: content-box, border-box;
虽然支持的属性值挺多,但是对于普通元素而言,目前生效的其实就前面3个。
做了个demo,演示不同mask-origin属性值的不同表现,您可以狠狠的点击这里:mask-clip不同属性值与遮罩效果demo
例如,已知CSS如下:
.mask-image {
width: 250px; height: 187.5px;
-webkit-mask-image: url(loading.png);
mask-image: url(loading.png);
border: 20px solid #34538b;
padding: 20px;
margin: 20px;
}
则我们选择content-box效果:
fill-box,stroke-box,view-box要与SVG元素关联才有效果,目前还没有任何浏览器对其进行支持。
九、mask-size属性详细介绍
mask-size属性性质上和background-size类似,支持的属性值也类似,作用是控制遮罩图片尺寸。
默认值是auto.
支持contain和cover这两个关键字:
mask-size: cover;
mask-size: contain;
支持各类数值(缺省高度会自动计算为auto):
mask-size: 50%;
mask-size: 3em;
mask-size: 12px;
mask-size: 50% auto;
mask-size: 3em 25%;
mask-size: auto 6px;
同样支持多属性值:
mask-size: 50%, 25%, 25%;
mask-size: 6px, auto, contain;
效果演示,如下CSS:
.mask-image {
width: 250px; height: 187.5px;
-webkit-mask-image: url(star.svg);
mask-image: url(star.svg);
-webkit-mask-size: cover;
mask-image: cover;
}
结果效果如下图(Chrome和Firefox浏览器均如此):
眼见为实,您可以点击这里:mask-size:cover与图片遮罩效果demo
十、mask-type属性简介
mask-type属性功能上和mask-mode类似,都是设置不同的遮罩模式。但还是有个很大的区别,那就是mask-type只能作用在SVG元素上,本质上是由SVG属性演变而来,因此,Chrome等浏览器都是支持的。但是mask-mode是一个针对所有元素的CSS3属性,Chrome等浏览器并不支持,目前仅Firefox浏览器支持。
由于只能作用在SVG元素上,因此默认值表现为SVG元素默认遮罩模式,也就是默认值是luminance,亮度遮罩模式。如果需要支持透明度遮罩模式,可以这么设置:
mask-type: alpha;
十一、mask-composite属性详细介绍
mask-composite表示当同时使用多个图片进行遮罩时候的混合方式。支持属性值包括:
mask-composite: add;
mask-composite: subtract;
mask-composite: intersect;
mask-composite: exclude;
以上属性值,目前仅Firefox浏览器支持,Chrome默认mask-composite计算值是source-over,和标准默认值add有些差异,作用是一样的,表示多个图片遮罩效果是累加。
各属性值释义如下:
add
遮罩累加。
subtract
遮罩相减。也就是遮罩图片重合的地方不显示。意味着遮罩图片越多,遮罩区域越小。
intersect
遮罩相交。也就是遮罩图片重合的地方才显示遮罩,。
exclude
遮罩排除。也就是后面遮罩图片重合的地方排除,当作透明处理。
为了演示不同mask-composite属性值的不同表现,特意做了个可交互的demo,您可以狠狠的点击这里:mask-composite不同属性值与遮罩效果demo
demo使用CSS代码:
.mask-image {
width: 250px; height: 187.5px;
-webkit-mask-image: url(loading.png), url(star.svg);
mask-image: url(loading.png), url(star.svg);
}
例如,Firefox浏览器下,选择mask-composite:subtract,则效果如下截图所示:
更新于2019-03-21Chrome浏览器mask-composite支持的属性值有变化,如下:
mask-composite:source-over;
mask-composite:source-in;
mask-composite:source-out;
mask-composite:source-atop;
mask-composite:destination-over;
mask-composite:destination-in;
mask-composite:destination-out;
mask-composite:destination-atop;
mask-composite:plus-lighter;
mask-composite:copy;
mask-composite:clear;
mask-composite:xor;