Key CSS Mask Properties
Masks in CSS are controlled by a group of properties that all work together. If you want to get the most out of masking, it’s important to understand each one clearly. Let’s go step by step.
1. mask-image
The mask-image property is the heart of CSS masking. It tells the browser what to use as the mask. This can be:
.element {
mask-image: url("mask-shape.png"); /* external image */
}
.element {
mask-image: linear-gradient(black, transparent); /* gradient fade */
}
.element {
mask-image: url(#mask1); /* referencing an SVG mask defined inline */
}
If the value is none (the default), no mask is applied. You can also apply more than one mask at the same time. This works just like multiple backgrounds: you separate each mask with a comma, and each one becomes a layer. The browser then combines them in order.
.element {
mask-image:
url("circle.png"),
linear-gradient(black, transparent);
}
In this example, the first mask layer is a circle image (circle.png) and the second mask layer is a gradient fade.
The final visible area is the result of combining both layers. Imagine stacking two stencils: the element only shows through where both masks allow it. This is where mask-composite (explained later) becomes important, because it defines how those layers mix together (add, subtract, intersect, etc.).
2. mask-mode
Once you’ve set a mask-image, the browser needs to know how to interpret it. That’s where mask-mode comes in.
There are two main modes:
alpha → uses transparency (alpha channel). Black or solid = visible, transparent = hidden.
luminance → uses brightness (light vs dark). White = visible, black = hidden.
match-source (default) → automatically chooses based on the source.
.element {
mask-image: url("mask-luminance.png");
mask-mode: luminance;
}
Use alpha for PNGs or gradients with transparent areas, and luminance if you’re working with masks where brightness should control visibility.
3. mask-repeat
By default, masks tile (repeat) if they’re smaller than the element — just like backgrounds do. You can control this with mask-repeat.
.element {
mask-image: url("pattern.png");
mask-repeat: repeat-x; /* repeats horizontally */
}
Values include:
In most design cases, you’ll want no-repeat for single masks, unless you’re intentionally creating a repeated pattern.
4. mask-position and mask-size
These two properties define where the mask sits and how big it is.
mask-position: aligns the mask (e.g., left, center, 20px 30px).
mask-size: scales the mask (cover, contain, or fixed dimensions).
mask-image: url("circle.png");
mask-position: center;
mask-size: 120px 120px;
mask-repeat: no-repeat;
}
In this example, the mask is centered on the element and fixed to 120px × 120px.
Together, mask-position and mask-size are essential when working with image masks.
5. mask-clip
Sometimes you don’t want the mask to apply to the entire box. mask-clip controls which box area is masked:
border-box (default) → includes the border.
padding-box → includes padding but not the border.
content-box → only the content area.
.element {
mask-image: url("mask.png");
mask-clip: content-box;
}
This is useful when you want the mask effect only inside the content and not spilling into padding or borders.
6. mask-origin
This property works with mask-position and mask-size. It decides the reference box used for positioning the mask. It accepts the same values as mask-clip (border-box, padding-box, content-box).
.element {
mask-image: url("mask.png");
mask-origin: padding-box;
mask-position: center;
}
Think of it as “from where should we start counting when placing the mask?”
7. mask-composite
When you use multiple masks, this property defines how they interact. The values are:
add → layers combine (union).
subtract → subtracts one mask from another.
intersect → only keeps overlapping areas.
exclude → keeps areas that do not overlap.
.element {
mask-image: url("circle.png"), url("star.png");
mask-composite: add, intersect;
}
This means the first layer (circle) is applied, and then the second layer (star) is combined with it using an intersect (only the overlapping areas show).
Masks vs. Clipping
At first glance, clipping (clip-path) and masking (mask) seem similar: both hide parts of an element and let only certain areas show. But there’s a key difference in how they work:
clip-path creates hard edges. You can cut an element into a circle, polygon, or other geometric shape, but the edges are always sharp and binary (either visible or hidden). There’s no fading or partial transparency.
mask is much more flexible. It can use transparency and gradients, which means you can create smooth fades, soft edges, or even use complex images (like PNGs or SVGs) to decide what shows and what doesn’t.
In practice, if you want something simple and sharp (like a circle avatar image or a hexagon card), clip-path is the quicker, easier choice. If you want fades, blends, or creative effects (like a photo that dissolves at the edges, or a shape with feathered transparency), mask is the way to go.
Real Examples of CSS Masks
Up until now, we’ve gone through the theory: how masks work, the properties that control them, and how they differ from clip-path.
But the real magic of masks comes when you actually see them in action. Let’s go through a few practical, real-world examples. Each one will show you not just the code, but also explain why it works the way it does.
Example 1: Creating a Circular Image Mask
The most basic use of a mask is to turn a regular rectangle image into a neat circle. You might think, “why not just use border-radius: 50%?” — and you’d be right for simple shapes. But masks go further: you can use them for non-geometric shapes, transparency, and more creative controls.
Here’s a simple circular mask with CSS:
<div class="circle-mask"></div>
.circle-mask {
width: 250px;
height: 250px;
background: url("https://picsum.photos/id/1015/400/400") center/cover no-repeat;
mask-image: radial-gradient(circle, black 70%, transparent 72%);
mask-repeat: no-repeat;
mask-position: center;
mask-size: cover;
-webkit-mask-image: radial-gradient(circle, black 70%, transparent 72%);
-webkit-mask-repeat: no-repeat;
-webkit-mask-position: center;
-webkit-mask-size: cover;
}
You’d ask, what’s happening here?
The background image fills the box.
The mask-image is a radial gradient: the center is solid black (meaning “show this”), and it fades to transparent outside (meaning “hide this”).
Because black = visible and transparent = hidden in mask-image, the result is a circular crop of the image.
Unlike border-radius, this same idea could be extended to stars, polygons, or custom patterns without touching the HTML.
Example 2: Fading Out the Bottom of an Image
One of the coolest features of masks is their ability to handle gradients, something clipping can’t do.
This makes it really easy to fade images into the background, a common trick in modern web design.
<div class="fade-mask"></div>
.fade-mask {
width: 400px;
height: 250px;
background: url("https://picsum.photos/id/1018/600/400") center/cover no-repeat;
mask-image: linear-gradient(to bottom, black 70%, transparent 100%);
mask-repeat: no-repeat;
mask-position: center;
mask-size: cover;
-webkit-mask-image: linear-gradient(to bottom, black 70%, transparent 100%);
-webkit-mask-repeat: no-repeat;
-webkit-mask-position: center;
-webkit-mask-size: cover;
}
The mask uses a linear gradient where the top 70% of the image stays fully visible and the bottom gradually fades to transparent, making the photo smoothly disappear into the page background — a perfect effect for blog headers, hero sections, or scroll-based designs.
Example 3: Combining Multiple Masks
Here’s where things get interesting. You can apply more than one mask at the same time. Imagine stacking stencils: only the overlapping areas are visible.
<div class="multi-mask"></div>
.multi-mask {
width: 350px;
height: 250px;
background: url("https://picsum.photos/id/1003/600/400") center/cover no-repeat;
mask-image:
radial-gradient(circle at center, black 70%, transparent 72%),
linear-gradient(to bottom, black 70%, transparent 100%);
mask-repeat: no-repeat, no-repeat;
mask-position: center, center;
mask-size: cover, cover;
-webkit-mask-image:
radial-gradient(circle at center, black 70%, transparent 72%),
linear-gradient(to bottom, black 70%, transparent 100%);
-webkit-mask-repeat: no-repeat, no-repeat;
-webkit-mask-position: center, center;
-webkit-mask-size: cover, cover;
}
What happens here is that the first mask layer cuts the image into a circle, the second fades out the bottom, and together they create a photo that not only has a circular shape but also gradually disappears toward the bottom — with mask-composite available if you need finer control over how the layers blend.