概览
如需将元素剪裁为复杂的自由形式形状(例如笔触或有机纹理),请使用 CSS 遮罩 (mask-image)。虽然 clip-path 非常适合几何形状或矢量路径,但 mask-image 允许您使用图片(例如具有透明度的 PNG)或 SVG 来定义元素的可见区域。这种方法更具表现力,因为它支持半透明,可实现柔和的边缘和复杂的纹理,而这些效果使用 clip-path 很难或无法实现。
实现
如需使用 CSS 遮罩实现复杂形状,请执行以下操作:
使用图片中的透明度
您可以将图片的透明度用作遮罩,其中不透明部分可见,透明部分隐藏。这可以是 PNG、SVG 或其他具有透明度的图片,也可以是生成的图片,例如 CSS 渐变。
.shaped-element {
/* MANDATORY: Use vendor prefix for wider support in older browsers */
-webkit-mask-image: url('mask.svg');
-webkit-mask-size: cover; /* Scale mask to cover element */
-webkit-mask-repeat: no-repeat; /* Do not tile the mask */
/* Standard property for modern browsers */
mask-image: url('mask.svg');
mask-size: cover;
mask-repeat: no-repeat;
}
在 HTML 中使用 SVG 元素
您还可以引用网页 HTML 中内嵌 SVG 内定义的 <mask> 元素。使用 maskContentUnits="objectBoundingBox" 可使遮罩随元素的大小自动缩放。这会告知浏览器将遮罩内的所有坐标解读为 0 到 1 之间的分数(例如 0.5 表示 50%),而不是绝对像素。
亮度遮罩与 Alpha 遮罩:默认情况下,SVG 遮罩使用亮度(明暗度)来确定不透明度,其中白色表示显示,黑色表示隐藏,灰色表示半透明。如果您希望遮罩改用 SVG 形状的 Alpha 通道(透明度),可以在 CSS 中指定
mask-type: alpha;,或直接在 SVG<mask>元素上指定mask-type="alpha"。
<!-- White areas reveal content, gray creates semi-transparency, black or transparent hides it -->
<svg width="0" height="0">
<defs>
<!-- objectBoundingBox scales mask coordinates (0 to 1) with the element's size -->
<mask id="custom-shape" maskContentUnits="objectBoundingBox">
<!-- Use white shapes to define fully opaque areas -->
<circle cx="0.5" cy="0.5" r="0.5" fill="white" />
<!-- Use gray shapes to define semi-transparent/faded areas -->
<circle cx="0.5" cy="0.5" r="0.25" fill="gray" />
</mask>
</defs>
</svg>
<div class="masked-content">
<!-- Content to be masked -->
</div>
<style>
.masked-content {
/* Reference the SVG mask ID */
-webkit-mask-image: url(#custom-shape);
mask-image: url(#custom-shape);
}
</style>
后备策略
如果浏览器不支持 mask-image 或带前缀的版本:
- 该元素不会被剪裁,而是显示为普通矩形。
- 确保在没有遮罩的情况下,内容仍然可读,且布局不会损坏(渐进增强)。
- (可选)使用特征检测功能,通过
clip-path提供更简单的后备形状。
/* Fallback for browsers that do not support masking */
@supports (not (mask-image: url(x))) and (not (-webkit-mask-image: url(x))) {
.shaped-element {
/* Use a simple rounded rectangle as fallback */
clip-path: inset(5% round 15px);
}
}