mask-image 配合渐变或 SVG 可实现真正透底镂空,黑色区域保留显示、透明区域透底,需兼容 -webkit-mask-image、设置 mask-repeat: no-repeat 和 mask-size: cover,SVG 需 fill="black" 表示显示区,luminance 模式下白显黑隐。

直接用 mask-image 配合渐变或 PNG/SVG 遮罩图,就能做出真正“透底”的镂空卡片——不是靠半透明叠加模拟,而是让底层内容原样穿透显示,这是 clip-path 或 backdrop-filter 根本做不到的。
用线性渐变创建矩形/圆形镂空区域
最轻量的方案是不用图片,纯 CSS 渐变定义镂空形状。关键点在于:遮罩中黑色(#000)代表“保留显示”,透明(transparent)才代表“镂空透底”。
-
mask-image: linear-gradient(to bottom, transparent 0%, transparent 40%, black 40%, black 60%, transparent 60%, transparent 100%)可以在中间切出一条横条镂空区 - 要镂空一个圆,改用
radial-gradient(circle at 50% 50%, transparent 0%, transparent 60%, black 60%, black 100%),注意半径百分比需根据容器尺寸微调 - 必须同时写
-webkit-mask-image和标准mask-image,否则 Safari 16.4+ 以外的版本不生效 - 别漏掉
mask-repeat: no-repeat和mask-size: cover,否则渐变可能平铺错位
用 SVG 作为 mask-image 实现任意复杂镂空
当需要多边形、文字轮廓、不规则缺口时,SVG 是唯一可靠选择。它支持矢量缩放,且可内联嵌入避免额外请求。
- 内联 SVG 示例:
mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='100' height='100'%3E%3Cpath d='M20,20 L80,20 L80,80 L20,80 Z' fill='black'/%3E%3C/svg%3E") - 路径中
fill="black"的区域会显示,fill="white"或未填充部分才是镂空区(注意:mask 默认以 luminance 模式解析,白=100%可见,黑=0%可见,灰度值决定透明度) - 如果 SVG 内使用了
fill="none"或透明色,务必加mask-mode: luminance显式声明解析方式,否则 Firefox 可能误判 - 避免在 SVG 中使用外部引用(如
<image href="...">),内联资源才保证离线可用
与 backdrop-filter 混合使用时的层级陷阱
想让镂空区下方呈现毛玻璃效果?不能简单套 backdrop-filter: blur(8px) —— 它只对“被遮罩元素自身背景后的区域”生效,而镂空区实际显示的是更底层的 DOM 元素,backdrop-filter 对它们无效。
立即学习“前端免费学习笔记(深入)”;
- 正确做法:把需要模糊的背景层单独抽出来,设为固定定位 +
backdrop-filter,再用mask-image控制上层卡片的镂空区域对齐它 - 常见错误:给镂空卡片自身加
backdrop-filter,结果只有卡片非镂空部分模糊,镂空区直接透出原始未模糊背景 - z-index 必须严格分层:模糊背景层(z: 1)→ 镂空卡片(z: 2)→ 卡片内容(z: 3),否则 mask 会裁错位置
- 在移动端 iOS Safari 中,
backdrop-filter+mask-image同时启用时,偶尔触发渲染闪烁,可加transform: translateZ(0)强制硬件加速缓解
鼠标跟随镂空的响应式实现要点
动态镂空本质是实时更新遮罩偏移,但直接 JS 改 style.maskPosition 性能差;用 CSS 自定义属性 + calc() 是更优解。
- 监听
mousemove时,计算归一化坐标:el.style.setProperty('--x', ev.offsetX / el.offsetWidth),同理--y - CSS 中用:
mask-position: calc(var(--x) * 100%) calc(var(--y) * 100%),配合mask-size: 200px 200px控制镂空大小 - 必须设置
mask-origin: content-box,否则偏移基准点会随 padding/border 偏移,导致跟随错位 - 在高 DPI 屏幕下,
offsetX/Y可能精度不足,建议改用ev.clientX - el.getBoundingClientRect().left并除以el.clientWidth
真正难的不是写出第一版镂空,而是确保它在 Safari、Chrome、Firefox 的 mask 解析模式一致,且和 backdrop-filter、transform、will-change 等属性共存时不崩溃——这些细节往往只在真机测试阶段暴露。


















