HTML5无原生渐变遮罩,需用canvas(createLinearGradient+globalCompositeOperation='destination-in')或SVG(+)实现;CSS mask-image支持有限,filter/backdrop-filter不具遮罩能力。

HTML5 本身没有“渐变遮罩滤镜”这个内置功能,所谓“HTML5 滤镜做渐变遮罩”,实际是靠 canvas 的 createLinearGradient 或 createRadialGradient 配合 globalCompositeOperation 实现的遮罩效果,或者用 SVG + 嵌入 HTML;CSS 滤镜(如 filter: blur())不支持遮罩逻辑。
canvas 中用渐变+合成模式实现遮罩
核心思路:先画遮罩层(渐变),再画内容图,通过 globalCompositeOperation = 'destination-in' 让内容只保留在渐变区域内。
-
globalCompositeOperation = 'destination-in'表示“只保留目标图像(即已绘制的内容)与源图像(即新画的渐变)重叠且不透明的部分” - 必须按顺序绘制:先画内容(比如一张图片),再画渐变,再设合成模式——但注意:合成模式要在画渐变前设置,否则无效
- 渐变坐标需匹配 canvas 坐标系,不是图片自身尺寸;若图片缩放或居中,要手动换算渐变起止点
- 示例关键片段:
const ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0); // 先画图
ctx.globalCompositeOperation = 'destination-in'; // 关键:设合成模式
const grad = ctx.createLinearGradient(0, 0, canvas.width, 0);
grad.addColorStop(0, 'rgba(255,255,255,1)');
grad.addColorStop(1, 'rgba(255,255,255,0)');
ctx.fillStyle = grad;
ctx.fillRect(0, 0, canvas.width, canvas.height); // 画渐变遮罩
SVG mask + linearGradient 是更稳定的选择
比起 canvas 手动控制绘图顺序和坐标,SVG 的 天然支持渐变遮罩,兼容性好、响应式友好、代码更声明式。
- 把
定义在里,再被引用,最后用mask属性挂到目标元素上 - 注意:mask 默认使用 alpha 通道,所以渐变色应为灰度(
#000完全遮挡,#fff完全显示) - mask 单位默认是 objectBoundingBox(0–1 范围),适合响应式;若需像素单位,改用
userSpaceOnUse - 示例结构:
@@##@@
为什么不用 CSS filter 或 backdrop-filter 做渐变遮罩?
因为它们作用对象不同:filter 是对元素自身渲染结果做后处理(模糊、变色等),backdrop-filter 是对元素背后区域做处理,二者都不具备“按透明度裁剪显示区域”的能力。
立即学习“前端免费学习笔记(深入)”;
- 试图用
opacity或rgba()背景模拟遮罩,只是视觉叠加,不是真遮罩——背后内容仍可被选中、触发事件、影响布局 -
clip-path支持inset()或path(),但不支持渐变;它只能硬边裁剪,无法实现软边淡出 - 目前唯一原生支持渐变遮罩的 CSS 方案是
mask-image: linear-gradient(...),但它在 Safari 15.4+ 和 Chrome 101+ 才稳定,且需要加-webkit-mask-image前缀兼容
真正落地时,SVG 方案最省心;canvas 方案适合需要逐帧控制或动态生成遮罩的场景;而纯 CSS 的 mask-image 看似简洁,但浏览器支持断层明显,移动端尤其容易失效。别忽略 mask 的默认坐标系和颜色空间——灰度值错一位,整个遮罩就反了。










