← Back to CSS Course | Chapter 9: Modern CSS Features | Lesson 9 of 25

CSS Masking

Imagine a stencil laid over a can of spray paint: wherever the stencil is solid, paint gets blocked; wherever it's cut away, paint passes through freely. Gray areas on the stencil would let some paint through, partially. CSS masking works exactly like that stencil, using an image or gradient's transparency to decide what parts of an element are visible.
Syntax
css
selector {
  mask-image: url("mask.png") | linear-gradient(...);
  mask-size: size;
  mask-repeat: no-repeat;
}

What mask-image Does

mask-image applies an image (or gradient) as a stencil over an element: fully opaque areas of the mask keep the element fully visible, fully transparent areas hide it completely, and partially transparent areas make the element partially visible.

Unlike a background image, the mask's own pixel colors are ignored, only its alpha channel matters.

Note:
  • Accepted values:
  • mask-image — none, url(), or a gradient
  • mask-mode — alpha | luminance | match-source
  • mask-repeat — repeat | no-repeat | space | round
  • mask-position — keywords, lengths, or percentages
  • mask-size — auto | cover | contain | length
  • mask-composite — add | subtract | intersect | exclude

Example: What mask-image Does

css
<style>
.box {
  width: 150px;
  height: 150px;
  background: crimson;
  mask-image: radial-gradient(circle, black 50%, transparent 70%);
}
</style>
<div class="box"></div>

mask-image vs clip-path

clip-path only supports hard geometric edges (a shape is either fully inside or fully outside the clip region, no partial transparency), while mask-image supports smooth, soft-edged transitions because it can use any grayscale or alpha gradient -- masking is the right tool when you need a fade, clip-path when you need a crisp cut.

Note:
  • Accepted values:
  • clip-path: <basic-shape> | url() | none — clips to a shape, hard edges only
  • mask-image: <image> | none — soft edges from the image's alpha
  • mask-image: linear-gradient(black, transparent) — fades out
  • inherit | initial | unset | revert — CSS-wide keywords accepted by every property

Example: mask-image vs clip-path

css
<style>
.masked {
  width: 100px;
  height: 100px;
  background: blue;
  mask-image: linear-gradient(black, transparent);
}
.clipped {
  width: 100px;
  height: 100px;
  background: green;
  clip-path: circle(50%);
}
</style>
<div class="masked"></div>
<div class="clipped"></div>

mask-size and mask-position

mask-size and mask-position control the scaling and placement of the mask image, using the same syntax and keywords (cover, contain, percentages) as background-size and background-position -- letting a mask be scaled independently of the element it's applied to.

Note:
  • Accepted values:
  • mask-size: auto — default, natural size
  • mask-size: cover — scales to cover the box
  • mask-size: contain — scales to fit inside
  • mask-size: <length> <length> — explicit size
  • mask-position: <position> — e.g. center, top left, 50% 50%
  • inherit | initial | unset | revert — CSS-wide keywords accepted by every property

Example: mask-size and mask-position

css
<style>
.box {
  width: 200px;
  height: 100px;
  background: orange;
  mask-image: url('https://placehold.co/50x50');
  mask-size: 50px;
  mask-position: center;
}
</style>
<div class="box"></div>

mask-repeat

mask-repeat controls whether the mask image tiles across the element, works exactly like background-repeat, and is useful for applying a small repeating pattern (like a dot-grid or diagonal-stripe mask) across a larger surface rather than stretching one mask image.

Note:
  • Accepted values:
  • repeat — default, tiles both axes
  • repeat-x — tiles horizontally only
  • repeat-y — tiles vertically only
  • no-repeat — draws once
  • space — tiles whole copies and spaces them out
  • round — tiles whole copies, scaling them to fit
  • inherit | initial | unset | revert — CSS-wide keywords accepted by every property

Example: mask-repeat

css
<style>
.box {
  width: 200px;
  height: 100px;
  background: teal;
  mask-image: url('https://placehold.co/20x20');
  mask-repeat: repeat;
}
</style>
<div class="box"></div>

Combining Multiple Masks and Fading Edges

Multiple comma-separated mask-image values layer like multiple background images, and a very common real-world pattern is using a linear-gradient mask to fade an image or long block of text smoothly into transparent at its edges, avoiding a harsh visual cutoff.

Note:
  • Accepted values:
  • mask-image: A, B — comma-separated layers
  • mask-composite: add — default, layers are unioned
  • mask-composite: subtract — top layer minus the layers below
  • mask-composite: intersect — only overlapping parts remain
  • mask-composite: exclude — only non-overlapping parts remain
  • inherit | initial | unset | revert — CSS-wide keywords accepted by every property

Example: Combining Multiple Masks and Fading Edges

css
<style>
.box {
  width: 300px;
  height: 100px;
  background: url('https://placehold.co/300x100');
  mask-image: linear-gradient(90deg, transparent, black 20%, black 80%, transparent);
}
</style>
<div class="box"></div>
Live Example
Related Topics
{# common_mistakes/chapter_summary/browser_support: on Hindi pages the view already swaps in the hi_ translation fields (or blanks these out if untranslated), so this renders correctly for both languages without a lang_code check here. #}
Common Mistakes
  1. Using mask-image without the -webkit- prefix in browsers that need it.
  2. Using an opaque image as a mask, so nothing is hidden; masks use alpha or luminance.
  3. Confusing mask-image with clip-path, since masks can fade edges while clip-path cuts hard edges.
Browser Support

Unprefixed mask-image is supported in Chrome 120+, Firefox 53+ and Safari 15.4+; older Chrome and Safari need the -webkit- prefix.

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.