Cutting out an image or a block into a shape that is not a simple rectangle, circle, or polygon, such as a torn texture, a complex silhouette, or a progressive transparency gradient, goes well beyond what clip-path can do. That is exactly the role of mask: using an image, in grayscale or with a transparency channel, as a stencil that decides which areas of an element stay visible.
It is a powerful but under-known property, often discovered late by developers looking for a solution to a visual effect that felt impossible with plain CSS.
Definition
mask, and more precisely mask-image, applies an image as a mask on an element: the opaque or white areas of that image let the element show through normally, the transparent or black areas make it invisible, and the in-between areas create a progressive transparency. The source image can be a file, PNG or SVG, or a CSS gradient generated directly in CSS.
Basic syntax
.photo {
mask-image: url("star.svg");
mask-size: contain;
mask-repeat: no-repeat;
mask-position: center;
}The syntax deliberately reuses the vocabulary of background-image: mask-size, mask-repeat, and mask-position work exactly like their background counterparts, which makes the property quick to learn once that kinship is understood.
Masking with a gradient
A very common use is masking with a gradient instead of an external image, to create a progressive fade effect, for example text or an image that gently fades toward the bottom.
.fade {
mask-image: linear-gradient(to bottom, black 60%, transparent 100%);
}Here, no image file is needed at all: the gradient itself acts as the stencil, opaque across the first 60% of the height, then progressively transparent down to the bottom of the element.
Difference from clip-path
clip-path and mask solve a related but not identical need. clip-path cuts along a simple vector shape, defined by coordinates (circle, polygon, path), with an always-sharp boundary between visible and invisible. mask uses an image as a stencil, which allows progressive transitions, complex textures, and far richer shapes than a simple geometric outline.
| Criterion | clip-path | mask |
|---|---|---|
| Source of the shape | Geometric coordinates | Image, SVG, or gradient |
| Progressive transparency | No, sharp boundary | Yes, in-between zones possible |
| Performance cost | Low | Higher on large areas |
Difference from the SVG <mask>
The SVG language also has its own <mask> element, older and more powerful in certain respects: it can combine several shapes, native SVG gradients, and reuse the same mask across several elements through an identifier. The CSS mask property can actually point directly to an SVG mask defined elsewhere in the document.
.icon {
mask: url("#my-svg-mask");
}In practice, the CSS mask property is enough for the vast majority of common visual effects, while the SVG <mask> stays reserved for more specific needs, particularly when the mask must be shared across several elements or animated with fine control.
FAQ
mask behave the same way in every browser?Support is broad today, but some versions long required the -webkit-mask prefix, particularly on Safari: it remains wise to check exact compatibility before relying on it for an essential piece of the interface.
transition or a CSS animation?Yes, mask-position or mask-size can be animated like any other property, which makes it possible, for example, to slide a stencil across an image for a progressive reveal effect on hover.
Yes by default: mask only affects visual rendering, not the element's interactive area, which keeps its original rectangular shape for clicks, unless combined with pointer-events or additional clipping.