在设计世界中,遮罩(masking)是实现独特设计效果的流行技术,作为一名设计师,我已经使用过很多次,但我在网页上使用 CSS 遮罩的次数很少,我认为我不使用 CSS 遮罩的原因是浏览器支持情况,它们在 blink 浏览器(Chrome 和 Edge)中只支持了部分特性,而在 Safari 和 Firefox 中完全支持。
好消息是 CSS 遮罩将成为 Interop 2023 的一部分,这意味着我们应该期待跨浏览器支持(耶!!)。
在这篇文章中,我将介绍 CSS 遮罩是什么,它是如何工作的,以及输出一些结合它的用例和示例。
让我们开始吧。
什么是遮罩?#
简单地说,遮罩的工作方式是在不擦除元素的情况下将其部分隐藏。
参考以下图片:
我们有一张图片和一个遮罩,在像 Photoshop 这样的设计应用程序中,我们可以把图片插入到灰色形状内,这样就会产生一个蒙版的图像。
它的工作原理是隐藏图像的某些部分而不是擦除它(它们仍然在那里,只是被隐藏了)。
这就是遮罩的核心概念,使用一个形状来显示和隐藏元素的某部分,我们可以进一步探索更独特的遮罩内容。
例如,我们可以创建一个如下图那样的渐变遮罩。
在渐变中,有填充和透明像素,填充的部分是元素的一部分可见区域,透明的部分则是隐藏的部分。
在 Photoshop 中,我们可以向一组图层添加图层蒙版,该组内的内容将被遮罩。它的工作原理是使用画笔工具隐藏组的一部分从而实现遮罩。
被遮罩的内容并没有被擦除,而是被隐藏了(请注意组项目)。
好了,以上都偏理论,在接下来的文章中,我将介绍 CSS 遮罩的使用方式,它是如何工作的以及一些用例和示例。
如何在 CSS 中使用遮罩#
在 CSS 中,有几种遮罩元素的方式:
mask
属性clip-path
属性- SVG
<mask>
mask
属性和 clip-path
的主要区别在于前者用于图像和渐变,而后者用于路径,本文的重点将放在 mask
属性上。
在 CSS 中,我们有 mask
简写属性,类似于 background
属性一样,是的,你没看错。这就是我认为它容易记住语法的原因,因为它的语法与 background
属性完全相同,但具有少量其他属性。
而不是列出所有的 CSS 遮罩属性,我将逐步添加一个遮罩功能的示例,让你可以在视觉上发现差异。
CSS 背景如下所示:
.card__thumb {
background-image: url('hero-cool.png');
}
CSS 遮罩如下所示:
.card__thumb {
mask-image: url('hero-cool.png');
}
很酷,对吧?这让你理解和掌握 CSS 遮罩变得更加容易。
现在,让我们用 CSS 重新做一下最初的示例。
首先,我需要将形状导出为 png 图像。
假设我想将遮罩应用于该图像。
<img src="ahmad-shadeed-web-directions.jpg" alt="" />
img {
mask-image: url("shape.png");
}
你能预测出结果吗?默认情况下,遮罩会重复,其大小将等于遮罩图像本身,如下图所示:
为了恢复,我们需要将 mask-repeat
设置为 no-repeat
,就像 CSS 背景图像一样。
img {
mask-image: url("shape.png");
mask-repeat: no-repeat;
}
太棒了!请注意,遮罩位于左上角,可以通过 mask-position
更改它,再次注意,语法与 CSS 背景图片配置完全相同!
img {
mask-image: url("shape.png");
mask-repeat: no-repeat;
mask-position: center;
}
除了位置,我们还可以更改遮罩大小,这对于使用遮罩图像响应元素的大小很有用。
img {
mask-image: url("shape.png");
mask-repeat: no-repeat;
mask-position: center;
mask-size: 60%;
}
还有一些遮罩属性,但我现在不想用它们来打击你学习的兴趣,稍后我将用实际用例来介绍它们。
使用 CSS 渐变进行遮罩#
CSS 遮罩不仅仅是使用图像,我们还可以利用渐变来创建强大且有用的遮罩效果。
稍后我将展示一些有用的用例,但现在,我想重点介绍渐变如何与遮罩配合使用的基本原理。
在以下示例中,mask-image
由从全黑到透明的 CSS 线性渐变组成。
img {
mask-image: linear-gradient(#000, transparent);
}
根据 MDN 的说法:
默认情况下,这意味着遮罩图像的 alpha 通道将乘以元素的 alpha 通道,可以使用 mask-mode 属性来控制。
这意味着,你可以使用除黑色以外的任何颜色,遮罩仍将起作用,因为默认遮罩模式设置为 alpha
(稍后我将详细介绍此内容)。
img {
mask-image: linear-gradient(red, transparent);
}
同样,遮罩的概念是透明像素将被隐藏,以下是具有硬色停止的渐变的简化示例:
img {
mask-image: linear-gradient(#000 50%, transparent 0);
}
太酷了!现在,核心遮罩概念已经清晰了(我希望如此),让我们探索一些实际用例的 CSS 遮罩。
实际使用案例和示例#
淡化图像#
使用遮罩的一个有趣用途是使图像淡出并与其下面的背景混合。
考虑以下图像:
css-masking-use-case-fade-image-light.png
乍一看,你可能会想要添加一个与背景颜色相同的渐变。像这样:
.hero__thumb:after {
position: absolute;
inset: 0;
background: linear-gradient(to top, #f1f1f1, transparent)
}
虽然这可能会起作用,但当主背景颜色改变时,它就会失败,注意到主页横幅会出现顿挫感:
使用 CSS 遮罩,我们可以遮盖主页横幅,使其与任何背景颜色配合使用。
.hero__thumb {
mask-image: linear-gradient(#000, transparent);
}
就这样!现在淡化过渡效果是真实的,并且不会在更改主页面背景时失效,请参见以下示例:
遮罩文本内容:示例 1#
当我们想要显示长文本但空间不足以完全显示时,解决方案是在开头和结尾处淡化文本,然后,文本将在任一方向上动画以显示剩余内容。
考虑以下图像:
再次,使用渐变的 hack 不起作用,因为内容下面的背景被更改了,它可以是纯色或图像。
要在 CSS 中实现它,我们需要添加一个渐变遮罩,以在开头和结尾处淡化内容。
我喜欢在 CSS 渐变中做到这一点并查看结果,然后将其应用为遮罩,这有助于在使用其作为遮罩之前将渐变可视化。
.c-card__footer {
background-image: linear-gradient(90deg, transparent, #000 15%, #000 85%, transparent 100%);
}
有了上面的内容,我们就可以将其应用为遮罩。
.c-card__footer {
mask-image: linear-gradient(90deg, transparent, #000 15%, #000 85%, transparent 100%);
}
还不完美?我们可以微调渐变值,直到结果完美为止。
遮罩文本内容:示例 2#
这与前面的示例相同,但应用于垂直方向,我在 Instagram 的直播视频中看到过这种情况。
考虑以下图像:
请注意,内容从顶部被冲洗出来?这个小地方可以有供稿评论,操作和其他内容。使用 CSS 遮罩非常适合这样做。
首先,让我们看一下渐变。
在 CSS 中,它可能是这样的:
.whatever-the-class-name {
mask-image: linear-gradient(to bottom, transparent, #000);
}
遮罩列表#
我在研究 CSS 遮罩时看到了这个很酷的例子,这个想法是我们有一系列特征、课程或其他任何东西,我们想淡化文本来使用户对其中的内容更加好奇。
考虑以下示例:
你可以在左边看到一个列表,在最底部淡化,使用 CSS 遮罩非常适合此操作,因为它可以与下面的背景混合,无论是图像还是深色背景。
让我们看看遮罩渐变,了解其工作原理。
在 CSS 中,它看起来像这样:
.list {
mask-image: linear-gradient(to bottom, #000, transparent 95%);
}
有趣的图像效果#
使用 CSS 遮罩和渐变,创建视觉效果的可能性是无限的。这是一个简单的示例,说明我们如何为图像创建视觉效果。
这是我为此演示制作的快速设计。
你看到的图像效果包括 5 个线性渐变,通过为每个渐变添加不同的渐变位置,我们可以获得类似的效果。
让我们更详细地看看渐变:
.thumb {
mask-image: linear-gradient(to bottom, #000, #000),
linear-gradient(to bottom, #000, #000),
linear-gradient(to bottom, #000, #000),
linear-gradient(to bottom, #000, #000),
linear-gradient(to bottom, #000, #000);
mask-size: 18% 70%;
mask-position: 0 100%, 25% 25%, 50% 50%, 75% 0, 100% 50%;
mask-repeat: no-repeat;
}
从视觉上看,遮罩如下所示:
要在每个矩形的遮罩上创建淡出效果,我们需要更新每个渐变并包括 “transparent” 关键字。
.thumb {
mask-image: linear-gradient(to bottom, transparent, #000),
linear-gradient(to bottom, #000, transparent),
linear-gradient(to bottom, transparent, #000),
linear-gradient(to bottom, #000, transparent),
linear-gradient(to bottom, transparent, #000);
mask-size: 18% 70%;
mask-position: 0 100%, 25% 25%, 50% 50%, 75% 0, 100% 50%;
mask-repeat: no-repeat;
}
我们还可以在悬停时对遮罩大小或位置进行动画处理。
这很强大,想象一下,将其与基于滚动的动画结合起来,事情可能会失去控制(不过是以一种好的方式)。
圆角标签页#
我考虑为 UI 特效尝试 CSS mask,这个特效叫做 圆角标签页。
这个想法是我们希望以一种与元素的 border-radius
融合的方式将元素的侧面圆角化。
在这篇博客文章中,Chris Coyier 解释了一种使用多个伪元素实现的技巧,更动态的解决方案是使用 CSS mask。
首先,让我们更仔细地看一下我想要实现的形状。
形状由一个正方形和一个圆形组成,我们需要的是它们的交集。
如何实现呢?我们可以使用多层 mask 以及 mask-composite
属性在它们上面执行 composting 操作。
首先,我们需要创建一个元素来容纳 mask。
.nav-item.active:before {
content: "";
position: absolute;
left: 100%;
bottom: 0;
width: 24px;
height: 24px;
background-color: var(--active-bg);
}
在这个空间中,我们需要绘制一个圆和一个正方形以进行组合,幸运的是,我们可以通过混合线性和径向渐变来实现。
.nav-item.active:before {
content: "";
position: absolute;
left: 100%;
bottom: 0;
width: 24px;
height: 24px;
background-color: var(--active-bg);
background-image: linear-gradient(to top, #000, #000),
radial-gradient(circle 15px at center, #000 80%, transparent 81%);
background-size: 12px 12px, 100%;
background-position: bottom left, center;
background-repeat: no-repeat, repeat;
}
注意以下几点:
- 我为正方形添加了
12px 12px
作为大小。 - 正方形位于左下角。
- 正方形形状不需要重复。
上面只是为了视觉上说明两个渐变的效果,下一步是实现它们!在 CSS 遮罩中,我们可以使用 mask-composite
属性来组合两个形状。
.nav-item.active:before {
content: "";
position: absolute;
left: 100%;
bottom: 0;
width: 24px;
height: 24px;
background-color: var(--active-bg);
mask-image: linear-gradient(to top, red, red),
radial-gradient(circle 15px at center, green 80%, transparent 81%);
mask-size: 12px 12px, 100%;
mask-position: bottom left, center;
mask-repeat: no-repeat, repeat;
mask-composite: subtract;
}
这是上述形状的 CSS 右侧。对于另一个,我们只需更改 mask-position
即可翻转。
.nav-item.active:after {
/* 其他样式 */
mask-position: bottom right, center;
}
多个头像裁剪#
在我关于镂空效果的文章中,我探讨了使用 CSS 创建镂空的不同方法。
其中一个例子非常适合 CSS 遮罩。
使用 CSS 遮罩,我们可以使用径向渐变来实现该效果。
.avatar {
-webkit-mask-image: radial-gradient(ellipse 54px 135px at 11px center, #0000 30px, #000 0);
}
我强烈建议阅读这篇文章,因为有很多像这样的详细例子。
结论#
当我开始学习 CSS 遮罩时,资源有限,更重要的是,我们可以在日常工作流程中使用的实际用例非常少。我希望通过本文让你知道在下一个项目中在哪里可以使用 CSS 遮罩。
顺便说一句,我没有深入研究 mask-mode
等属性,因为说实话,我没有发现用它们来解决的问题(直到现在)。当我有一个更有说服力的使用这种属性的例子时,我会更新这篇文章。
更多资源#
如果您想在更多的 CSS 遮罩示例中提高自己的技能,那么您必须查看以下内容:
- 为你的头像提供华丽的悬停效果 by Temani Afif
- Mask Compositing: 快速入门课程 by Ana Tudor
- 仅使用 CSS 实现的语音泡 by Temani Afif
- 酷炫的梯度边框悬停效果 by Temani Afif
感谢您的阅读。