CSS mask properties
CSS masking is a technique that enables you to define visible portions of an element by applying a mask, which selectively reveals or hides parts of the element based on the alpha channels, and optionally colors, of the applied mask images.
Theintroductory guide to masking introduces the different types of mask images and their modes. The guide todeclaring multiple masks discusses themask layers and themask shorthand property, providing a brief introduction to the shorthand's component properties. In this guide, we explore these component properties in greater detail and look at how they interact. We also explain how, in cases where multiple mask images are declared, themask layers are composited, or combined.
CSS masks are composed of one or more mask layers, with a mask layer created for every value in the comma-separated list ofmask ormask-image values, whether the values are images, mask sources, or the keywordnone. Everymask-image ispositioned relative to anorigin box. The mask images can besized,repeated, andclipped, then composited together with previous layers to create the final visual mask on the element.
In this article
Themask-image property
The minimum requirement to create a mask is amask-image property set to a value other thannone.The keywordnone within a list of mask sources creates a mask layer. However, ifnone is the only value of themask-image property, no masking occurs.
The mask image can be aCSS gradient, animported image (such as a PNG, SVG, etc.), or an SVG<mask> element.
In this example, we create five mask layers, including an imported image, two gradients, a layer with no image, and an SVG<mask> source as the mask image.
.masked-element { mask-image: url("alphaImage.png"), linear-gradient(to right, black, transparent), radial-gradient(circle, white 50%, transparent 75%), none, url("#svg-mask");}Because one of the mask images is specified asnone, only four mask images are applied to the.masked-element element, while creating five mask layers.
The importance ofnone
Thenone layer generally has no visual effect (see themask-composite property for how it impacts the applied mask), but as each value in a comma-separated list ofmask-* values applies to a separate mask layer, thenone value serves an important purpose even when it doesn't change the composited mask.
This fourth layer in our five-layer structure will match the fourth value of any other comma-separatedmask-* property values. As previously mentioned, the number of layers is determined by the number of comma-separated values in themask-image property value, even if a value isnone. Eachmask-* value is matched up with themask-image values, in order. If the number of values in amask-* property differs from the number of mask layers, any excess values are ignored, or, if the property has fewer values than the number of mask layers, the values are repeated.
If amask-* property has a single value, this value applies to all the layers. If we have five values, the fourth value applies to thenone layer, with the last value being applied to the<mask> source layer. If there are two comma-separated values, the first value will apply to all the odd layers only, including that<mask> source layer. For example, eachmask-* property may have a different number of values:
.masked-element { mask-image: url("alphaImage.png"), linear-gradient(to right, black, transparent), radial-gradient(circle, white 50%, transparent 75%), none, url("#svg-mask"); mask-repeat: repeat-x, repeat-y; mask-position: center, top left, bottom right;}In this case, every odd layer will be repeated along the x-axis while every even layer is repeated along the y-axis. The first and fourth layer images will be centered, while the second and fifth will be positioned in the top left corner. Thenone means the fifth layer's#svg-mask image will be repeated along the x-axis starting at the top left corner.
Learn more aboutmask layers and thenone keyword.
Themask-mode property
Themask-mode property can be used to set the mode of each mask layer to eitheralpha orluminance, or allow it to default to the source's mode by setting the value tomatch-source, which is the default. While mostmask-* properties have an analogousbackground-* property (mask-image is analogous to thebackground-image property, for example),mask-mode andmask-composite have no analogousbackground property.
Mask types:alpha andluminance
Each mask is either analpha or aluminance mask.
Withalpha masks, the alpha-transparency of each mask pixel is important. Wherever the mask is opaque, the corresponding parts of the element will be visible. Wherever the mask is transparent, the corresponding parts of the element will be hidden. Wherever the mask is semi-opaque, the element will be equally semi-opaque. The color of the mask doesn't matter, just the alpha-transparency of the colors.
Withluminance masks, both thebrightness of mask's colors and the alpha channel determine the opaqueness of the masked areas.
Note:All subsequent examples use the following image as abackground-image on an element to which masks will be applied:

This example demonstrates the difference betweenalpha andluminance masks. The masks are the same, but in thealpha mask, only the alpha-transparency of the gradient mask colors matter. In theluminance example, the R, G, B, and A all matter.
Two containers contain images, while the last is empty but is included to display the gradient we will be using as ourmask-image.
<div> <img src="https://mdn.github.io/shared-assets/images/examples/progress-pride-flag.jpg" alt="Pride flag" /></div><div> <img src="https://mdn.github.io/shared-assets/images/examples/progress-pride-flag.jpg" alt="Pride flag" /></div><div></div>body { display: flex; gap: 20px; padding: 15px; background-image: conic-gradient( transparent 90deg, rgb(0 0 0 / 0.05) 90deg 180deg, transparent 180deg 270deg, rgb(0 0 0 / 0.05) 270deg ); background-size: 30px 30px;}div,svg,img { width: 220px; aspect-ratio: 1;}div { border: 1px solid black;}We declare arepeating-linear-gradient with red, transparent, and semi-transparent red diagonal stripes. This gradient is used as our mask and, for the last container, as the background image:
img { mask-image: repeating-linear-gradient( to bottom right, red 0 20px, #ff000055 20px 40px, transparent 40px 60px );}.gradient { background: repeating-linear-gradient( to bottom right, red 0 20px, #ff000055 20px 40px, transparent 40px 60px );}We set different values for themask-mode property for each image:
.alpha img { mask-mode: alpha;}.luminance img { mask-mode: luminance;}In thealpha case, only the transparency of the gradient's colors matter. Where the gradient is opaque red, the image is opaque. Where the gradient is transparent, the image is hidden. Where the gradient is 50% opaque, the image is 50% opaque. In theluminance case, the color's brightness matters! SeeAlpha transparency versus luminance to learn about the equation that uses the color's R, G, B, and A channels to determine the opacity of the mask.
Themask-mode default value:match-source
The default value of themask-mode property ismatch-source. This value sets themask-mode to match the mask's mode type. Thematch-source value resolves toalpha for every mask except masks where the mask source is an SVG<mask> element.
When an SVG<mask> element is used as the mask source, thematch-source value resolves to the value of the<mask> element'smask-type property. If the<mask> element (not the "masked element") doesn't have the CSSmask-type property defined, this property defaults to the value of the SVGmask-type attribute, if present. If that is omitted as well, thematch-source value will resolve toluminance.
Continuing with themasked-element example, if we don't explicitly set themask-mode property, it will default tomatch-source for each layer, as if we had set the following:
.masked-element { mask-image: url("alphaImage.png"), linear-gradient(to right, black, transparent), radial-gradient(circle, white 50%, transparent 75%), none, url("#svg-mask"); mask-mode: match-source;}or, using themask shorthand:
.masked-element { mask: url("alphaImage.png") match-source, linear-gradient(to right, black, transparent) match-source, radial-gradient(circle, white 50%, transparent 75%) match-source, none match-source, url("#svg-mask") match-source;}The first mask layer,url("alphaImage.png"), references an image. As this isn't a<mask> element within an<svg>, themask-mode resolves toalpha, with the opaque parts of this image making the corresponding parts of the element visible, while the transparent or semi-transparent parts are invisible or partially visible.
Thelinear-gradient(to right, black, transparent) is the second mask layer andradial-gradient(circle, white 50%, transparent 75%) is the third. Again, these aren't<mask> elements, so thematch-source value resolves toalpha. The masking effect of these layers is determined by theopaqueness of the gradient mask by default.
The fourth mask layer hasnone declared, meaning the mask for this layer is transparent black. The.masked-element class setsmask-mode: match-source;. Hadmask-mode instead been a comma-separated list of five different values, the fourth value would have applied to thisnone layer, allowing the fifth value to apply to the fifth layer.
The fifth mask layer is comprised of an SVG<mask> element that hassvg-mask as itsid. While the default mask mode of the other layers isalpha, the defaultmask type of SVG<mask> elements is themask-type value, or, if not set, themask-type attribute. If that isn't defined either, the value defaults toluminance. In other words, the masking effect of the<mask> is determined by both the brightness and transparency of the<mask> element's colors.
If we don't declare themask-mode property at all, and allow it default tomatch-source for each mask layer, the result in this.masked-element case would resolve to:
.masked-element { mask-image: url("alphaImage.png"), linear-gradient(to right, black, transparent), radial-gradient(circle, white 50%, transparent 75%), none, url("#svg-mask"); mask-mode: alpha, alpha, alpha, match-source, luminance;}or, using themask shorthand:
.masked-element { mask: url("alphaImage.png") alpha, linear-gradient(to right, black, transparent) alpha, radial-gradient(circle, white 50%, transparent 75%) alpha, none match-source, url("#svg-mask") luminance;}Themask-position property
Analogous to thebackground-position property, themask-position property sets the initial position of the mask image relative to the mask layer's origin box, defined bythemask-origin property. The syntax follows thebackground-position's<position> syntax, with the value being one, two, or four<position> values, defining one to two relative or absolute position offsets.
One-value syntax
If only one keyword value is specified, that value specifies the mask origin edge against which the mask will be placed with the other dimension beingcenter.
If only one<length-percentage> value is specified, this specifies the X coordinate relative to the left edge of the mask origin, with the Y coordinate set to50%.
If two keyword values are specified, the order of the value doesn't matter, but the value can not include two vertical or two horizontal axis values;left right andtop bottom are both invalid.
Two-value syntax
If two values are present, including one keyword and one<length-percentage> value, the order only matters if the keyword iscenter:
- If the keyword is
leftorright, it defines the X coordinate relative to the left edge, and the value defines the Y coordinate relative to the top edge. - Similarly, a
toporbottomkeyword defines the Y coordinate positioning the element against the top or bottom edge, respectively, with the other value defining the X value relative to the left edge of the mask origin box. - When one value is the
centerkeyword and the other is a<length-percentage>, the first value defines the horizontal position and the second value defines the vertical position.
If two values are present and both are<length-percentage> values, the order again matters; the first value defines the horizontal positioning as an offset from the left edge of the mask-positioning area while the second value defines the vertical position as an offset from the top edge of the mask-positioning area.
Four-value syntax
Mask positions can also be relative to corners other than the top left. The four-value syntax enables offsetting the mask from any corner. The value includes two<length-percentage> offsets, each preceded by the origin side for that offset. Whether you declare the horizontal or vertical pair first doesn't matter, but you must declare the origin-side keyword (left,right,top,bottom,x-start,x-end,y-start,y-end,block-start,block-end,inline-start, orinline-end) before the offset<length-percentage> in each pair, and the two origin-sides can't be from the same axis.
In the two<length-percentage> syntax, the origin sides aretop andleft, in that order. For example,mask-position: 10px 20px is the equivalent ofmask-position: left 10px top 20px. When offsetting from the top and left, the offset sides aren't required, but the order matters. With the four value syntax, you can usemask-position to offset the mask image from any edge combinations, such asleft 10px bottom 20px, and the order of the sides doesn't matter, as the offset edge is defined by the keyword preceding it rather than the declaration order.
Percentage values
When offsetting using percentage values, the mask's dimension is subtracted from the element's dimension, just as is done withpercentage offsets withbackground-position.
Positioning repeating mask images
Themask-position property defines the initial position of the mask image. By "initial position", if themask repeats, the browser places the first mask image in the position defined by themask-position property, thus defining the placement of the mask repetitions.
In this example, we set the position of the first image tobottom right, meaning the first mask will be placed at the bottom right edge of the mask origin box. Because mask images repeat by default, the repeating masks will be positioned against the first placed mask's top and left sides.
<div> <img src="https://mdn.github.io/shared-assets/images/examples/progress-pride-flag.jpg" alt="Pride flag" /></div><div> <img src="https://mdn.github.io/shared-assets/images/examples/progress-pride-flag.jpg" alt="Pride flag" /></div><div> <img src="https://mdn.github.io/shared-assets/images/examples/progress-pride-flag.jpg" alt="Pride flag" /></div>div,img { width: calc(30vw - 20px);}img { mask-image: url("https://mdn.github.io/shared-assets/images/examples/mask-star.svg");}.keywords img { mask-position: bottom right;}.twoValue img { mask-position: -20px -10px;}.fourValue img { mask-position: right -20px bottom -10px;}div::before { content: 'class="' attr(class) '"'; display: block; text-align: center; font-family: monospace;}body { flex-flow: row wrap;}Themask-position defines the position of the first mask image's placement. This demo shows where the first image is placed:
img { mask-repeat: no-repeat;}Because the default value for themask-repeat property isrepeat, the images are repeated along the X and Y axes, based on the position of that first mask:
The two-value example defines the top and left offsets of the original mask. The four-value example combines the previous two previous examples, position the first mask using the same offsets as the second image, but from the same edges as demonstrated in the first image.
In the first image, the first star to be placed is the one on the bottom right, with the repeated stars above and to the left. Because of this positioning, the initial star is not clipped, but the top-most and left-most stars are.
If we don't explicitly set themask-position property, it will default to0% 0% for each layer, with the top-left corner of the mask abutting the top-left corner of the mask origin box. Continuing with themasked-element example, it is as if we had set the following:
.masked-element { mask-image: url("alphaImage.png"), linear-gradient(to right, black, transparent), radial-gradient(circle, white 50%, transparent 75%), none, url("#svg-mask"); mask-mode: match-source; mask-position: 0% 0%;}or, expanding on the example using themask shorthand:
.masked-element { mask: url("alphaImage.png") 0% 0% match-source, linear-gradient(to right, black, transparent) 0% 0% match-source, radial-gradient(circle, white 50%, transparent 75%) 0% 0% match-source, none 0% 0% match-source, url("#svg-mask") 0% 0% match-source;}Themask-origin property
When an element has padding, a border, or both, themask-origin property defines which of these box edge values acts as the mask origin box, or themask positioning area, within which a mask image is positioned, for that layer. Themask-origin property is analogous to thebackground-origin property, but with a different initial value and SVG-only values.
HTML elements can have masks contained within their content border box, padding box, or content box. For example, if themask-position istop left, is that relative to the border's outer edge, the padding's outer edge, or the content's outer edge?
In themask-position masking example, the position defined was relative to the border-box (the default behavior), although it is worth noting that the<img> had no border or padding set, therefore the content-box, padding-box, and border-box origins would all be the same in this case.
<div> <img src="https://mdn.github.io/shared-assets/images/examples/progress-pride-flag.jpg" alt="Pride flag" /></div><fieldset> <legend>Set the <code>mask-origin</code> value</legend> <label ><input type="radio" name="origin" checked /> border-box</label > <label ><input type="radio" name="origin" /> padding-box</label > <label ><input type="radio" name="origin" /> content-box</label ></fieldset>div { all: unset;}legend { align-self: baseline;}label { display: block;}In this example, themask-position places the initial mask in the top left corner of the<img> element that has a large border and padding, with a green background color to enable seeing the star masking on the padding area.
img { mask-image: url("https://mdn.github.io/shared-assets/images/examples/mask-star.svg"); mask-position: top left; padding: 15px; border: 15px solid; background-color: green;}:has(#origin_border-box:checked) img { mask-origin: border-box;}:has(#origin_padding-box:checked) img { mask-origin: padding-box;}:has(#origin_content-box:checked) img { mask-origin: content-box;}Change the value of themask-origin property by changing the selected radio button, looking at the position of the top left star mask as you do so.
The default value isborder-box. With this value, the initial mask is placed at the border's top-left edge and is not clipped. When the initial mask is placed at the outer or inner edge of the padding, there is room above it and to the left; these repeating masks are clipped.
Continuing with themasked-element example, if we don't explicitly set themask-origin property, it will default toborder-box for each layer, as if we had set the following:
.masked-element { mask-image: url("alphaImage.png"), linear-gradient(to right, black, transparent), radial-gradient(circle, white 50%, transparent 75%), none, url("#svg-mask"); mask-mode: match-source; mask-position: 0% 0%; mask-origin: border-box;}or, expanding on the example using themask shorthand:
.masked-element { mask: url("alphaImage.png") 0% 0% border-box match-source, linear-gradient(to right, black, transparent) 0% 0% border-box match-source, radial-gradient(circle, white 50%, transparent 75%) 0% 0% border-box match-source, none 0% 0% border-box match-source, url("#svg-mask") 0% 0% border-box match-source;}For SVG elements, which don't have the associated CSS layout boxes, a mask can be contained inside the SVG element's fill, stroke, or view box.
Themask-clip property
Themask-clip property determines the area of the element that will be affected by a mask, effectively clipping the element at the defined box edge. It is analogous to thebackground-clip property, but with some different values.
Because themask-clip property accepts all themask-origin values and both have the sameborder-box default value, the two properties may seem similar, but they serve very different purposes. Whilemask-origin determines where a mask image will be positioned, themask-clip property causes the original element to have its content clipped to the specified box. It is important to understand them both: if themask-origin causes themask-position to place the mask image outside the clipping area, the mask will be clipped.
Themask-clip property accepts all themask-origin values, as well as its ownno-clip value. Theno-clip value sets the painted content not to be clipped. You can still cause the mask image to be clipped by positioning it outside of the border content area usingmask-position values that are less than zero or resolve to greater than 100%.
Setting themask-clip andmask-origin to different values can cause the mask layer image to be clipped. For example, if an element with a border and padding hasmask-clip set tocontent-box andmask-origin set toborder-box, and themask-position is set to thetop left edge, the mask layer image will be clipped at the top-left edge.
The next example adds clipping options to the previous example to demonstrate the different non-SVGmask-clip values and to show how they impact the differentmask-origin values.
<div> <img src="https://mdn.github.io/shared-assets/images/examples/progress-pride-flag.jpg" alt="Pride flag" /></div><fieldset> <legend>Set the <code>mask-clip</code> value</legend> <label ><input type="radio" name="clip" checked /> border-box</label > <label ><input type="radio" name="clip" /> padding-box</label > <label ><input type="radio" name="clip" /> content-box</label > <label><input type="radio" name="clip" /> no-clip</label></fieldset><fieldset> <legend>Set the <code>mask-origin</code> value</legend> <label ><input type="radio" name="origin" checked /> border-box</label > <label ><input type="radio" name="origin" /> padding-box</label > <label ><input type="radio" name="origin" /> content-box</label ></fieldset>:has(#clip_border-box:checked) img { mask-clip: border-box;}:has(#clip_padding-box:checked) img { mask-clip: padding-box;}:has(#clip_content-box:checked) img { mask-clip: content-box;}The first mask is placed at the top-left edge of the mask origin container, then repeated. If the origin box is theborder-box and the clipping region is thecontent-box, the top and left areas of the mask origin container will be clipped. Generally, you will want themask-clip to be the same as themask-origin.
Continuing with themasked-element example, if we don't explicitly set themask-clip property, it will default toborder-box for each layer, as if we had set the following:
.masked-element { mask-image: url("alphaImage.png"), linear-gradient(to right, black, transparent), radial-gradient(circle, white 50%, transparent 75%), none, url("#svg-mask"); mask-mode: match-source; mask-position: 0% 0%; mask-origin: border-box; mask-clip: border-box;}or, expanding on the example using themask shorthand:
.masked-element { mask: url("alphaImage.png") 0% 0% border-box border-box match-source, linear-gradient(to right, black, transparent) 0% 0% border-box border-box match-source, radial-gradient(circle, white 50%, transparent 75%) 0% 0% border-box border-box match-source, none 0% 0% border-box border-box match-source, url("#svg-mask") 0% 0% border-box border-box match-source;}In themask shorthand, if only one<geometry-box> value is given, it sets both themask-origin andmask-clip property values. If two<geometry-box> values are present, the first defines themask-origin and the second defines themask-clip.
For mask layer images that do not reference an SVG<mask> element, themask-clip property defines whether the mask painting area, or the area affected by the mask, is the border, padding, or content box. The painted content of the element will be restricted to this area.
When the mask layer'smask-image source is a<mask>, themask-clip property has no effect. Rather, the<mask> element'sx,y,width,height, andmaskUnits attributes determine the mask painting area.
Themask-size property
Themask-size property is used to size mask layers. This property is analogous to thebackground-size property, taking the same values. When sizing your masks, remember that areas of the element not covered by the mask images are hidden.
There are three ways to declare amask-size:
- the
coverorcontainkeyword, - one length, percentage, or the keyword
auto, or - two values that are a combination of lengths, percentages, and the keyword
auto.
The mask image can be left to its natural size, stretched, or constrained to fit the available space. Theaspect ratio of the mask image is maintained by default, but declaring two<length-percentage> values can distort the mask image if the ratio of the two values is not the same as the original image (mask-repeat: round is the other property/value pair that may distort the mask image).
If themask-size is set tocontain, the mask image will be the largest size it can be while being fully contained within the mask positioning area. In this case, the mask image is not clipped, but rather, it is fully contained.
When set tocover, the mask image will be the smallest size it can be to fully cover the entire mask-positioning area, with the mask being clipped if the mask's aspect ratio differs from the aspect ratio of the mask-positioning area.
In other words, Withcover andcontain, at least one dimension of the mask will be the same size as the mask-positioning area's same dimension; the mask image either grows or shrinks so that either the width is the same width as the mask positioning area or the mask image's height is equal to the mask positioning area's height.
Withcover,contain, and<percentage> values, the size is relative to the origin box. In our star-mask and flag image example, the aspect ratio of both the mask image and the<img> are1:1, meaning in this casecover,contain, and100% will all produce the same sized mask. This example demonstrates how, whenmask-size is set tocover,contain or a<percentage> value, the actual size of the mask may differ depending on the value of themask-origin property:
<div> <img src="https://mdn.github.io/shared-assets/images/examples/progress-pride-flag.jpg" alt="Pride flag" /></div><fieldset> <legend>Set the <code>mask-origin</code> value</legend> <label ><input type="radio" name="origin" checked /> border-box</label > <label ><input type="radio" name="origin" /> padding-box</label > <label ><input type="radio" name="origin" /> content-box</label ></fieldset>img { mask-image: url("https://mdn.github.io/shared-assets/images/examples/mask-star.svg"); mask-position: top left; padding: 15px; border: 15px solid; background-color: green;}img { mask-size: 100%;}:has(#border-box:checked) img { mask-origin: border-box;}:has(#padding-box:checked) img { mask-origin: padding-box;}:has(#content-box:checked) img { mask-origin: content-box;}Change the value of themask-origin property to see how the different values impact the mask size:
This example included one<percentage> value. When one<length-percentage> value is specified, it defines only the mask width, with the height defaulting toauto, which maintains the aspect ratio. When two values are specified, the first defines the mask width and the second defines its height.
The default value ofmask-size isauto, rendering the mask at itsintrinsic size, the size at which the mask would be displayed if no CSS were applied. The underlyingaspect ratio of the mask image is maintained if you set a single<length-percentage> value, or two values in the same ratio as the aspect ratio. If you declare two values not in the same ratio as the aspect ratio, the mask image is distorted.
Like with all longhand components of shorthand property, if themask shorthand property is set and the value of themask-size property is not defined within any mask layer, themask-size value is reset to its initial value ofauto for those mask layers.
If the image has no intrinsic proportion, for example in the case of aCSS gradient, the defaultauto is the entirety of the mask positioning area as set bythemask-origin property.
Continuing with themasked-element example, if we don't explicitly set themask-size property, it will default toauto for each layer, as if we had set the following:
.masked-element { mask-image: url("alphaImage.png"), linear-gradient(to right, black, transparent), radial-gradient(circle, white 50%, transparent 75%), none, url("#svg-mask"); mask-mode: match-source; mask-position: 0% 0%; mask-origin: border-box; mask-clip: border-box; mask-size: auto;}or, expanding on the example using themask shorthand, with themask-size component going after themask-position value, separated by a forward slash (/):
.masked-element { mask: url("alphaImage.png") 0% 0% / auto border-box border-box match-source, linear-gradient(to right, black, transparent) 0% 0% / auto border-box border-box match-source, radial-gradient(circle, white 50%, transparent 75%) 0% 0% / auto border-box border-box match-source, none 0% 0% / auto border-box border-box match-source, url("#svg-mask") 0% 0% / auto border-box border-box match-source;}Themask-repeat property
Themask-repeat property defines how mask images are repeated, or tiled, after the initial mask image has been sized and positioned. Themask-repeat property defines if and how that mask image is repeated along the horizontal and vertical axes. In most of the previous examples, you may have noticed the star mask repeated along the X and Y axes. This is becauserepeat is the default value.
Themask-repeat property is analogous to thebackground-repeat property, accepting the same<repeat-style> values. As is the case withbackground-repeat, the first (and possibly only) mask-image repetition is positioned bythe*-position property and sized bythe*-size property. The positions of the repeated background or mask images are based on this initial image instance.
Continuing with themasked-element example, if we don't explicitly set themask-repeat property, it will default torepeat for each layer, as if we had set the following:
.masked-element { mask-image: url("alphaImage.png"), linear-gradient(to right, black, transparent), radial-gradient(circle, white 50%, transparent 75%), none, url("#svg-mask"); mask-mode: match-source; mask-position: 0% 0%; mask-origin: border-box; mask-clip: border-box; mask-size: auto; mask-repeat: repeat;}or, expanding on the example using themask shorthand:
.masked-element { mask: url("alphaImage.png") 0% 0% / auto repeat border-box border-box match-source, linear-gradient(to right, black, transparent) 0% 0% / auto repeat border-box border-box match-source, radial-gradient(circle, white 50%, transparent 75%) 0% 0% / auto repeat border-box border-box match-source, none 0% 0% / auto repeat border-box border-box match-source, url("#svg-mask") 0% 0% / auto repeat border-box border-box match-source;}Themask-composite property
Themask shorthand includes themask-composite property, which defines how multiple masks are combined to create the final mask effect. Each value in the comma-separated list of values determines whether the browser shouldadd,subtract,intersect, orexclude the associated mask layer from or to the mask layers below it. Similar tomask-mode, and the othermask-* properties, there is no property in thebackground shorthand that is analogous.
<div> <img src="https://mdn.github.io/shared-assets/images/examples/progress-pride-flag.jpg" alt="Pride flag" /></div><div> <img src="https://mdn.github.io/shared-assets/images/examples/progress-pride-flag.jpg" alt="Pride flag" /></div><div> <img src="https://mdn.github.io/shared-assets/images/examples/progress-pride-flag.jpg" alt="Pride flag" /></div><div> <img src="https://mdn.github.io/shared-assets/images/examples/progress-pride-flag.jpg" alt="Pride flag" /></div>In this example, we include twomask-image values, including the star and the gradient from the previous examples as mask images:
img { mask-image: repeating-linear-gradient( to bottom right, red 0 20px, #ff000055 20px 40px, transparent 40px 60px ), url("https://mdn.github.io/shared-assets/images/examples/mask-star.svg");}We set a differentmask-composite value for each image:
.add img { mask-composite: add;}.subtract img { mask-composite: subtract;}.intersect img { mask-composite: intersect;}.exclude img { mask-composite: exclude;}div::before { content: "mask-composite: " attr(class); display: block; text-align: center; font-family: monospace;}body { flex-flow: row wrap;}The semi-transparent star mask is added to, subtracted from, intersected with, or excluded from the striped mask, depending on themask-composite value.
Themask-composite property is only relevant in cases with two or more mask layers. This reads "mask layers", not "mask images" because, ifnone is included, the transparent black mask is composited. Anone value can have a profound effect on masking in the case ofsubtract andintersect. For example, if themask-mode resolves toluminance, subtracting a black mask will remove the entire mask (the element will be hidden). Similarly, ifnone is the last layer withmask-composite: intersect set for that layer, the entire element will be hidden. Here, we add a third layer, withnone, to the previous example:
img { mask-image: url("https://mdn.github.io/shared-assets/images/examples/mask-star.svg"), repeating-linear-gradient( to bottom right, red 0 20px, #ff000055 20px 40px, transparent 40px 60px ), none;}Note how theintersect example excludes everything because the transparent black mask doesn't intersect anything.
If we reverse the order of the mask layers, we can also get very different results:
<div> <img src="https://mdn.github.io/shared-assets/images/examples/progress-pride-flag.jpg" alt="Pride flag" /></div><div> <img src="https://mdn.github.io/shared-assets/images/examples/progress-pride-flag.jpg" alt="Pride flag" /></div>.gradientFirst { mask-image: repeating-linear-gradient( to bottom right, red 0 20px, #ff000055 20px 40px, transparent 40px 60px ), url("https://mdn.github.io/shared-assets/images/examples/mask-star.svg");}.starFirst { mask-image: url("https://mdn.github.io/shared-assets/images/examples/mask-star.svg"), repeating-linear-gradient( to bottom right, red 0 20px, #ff000055 20px 40px, transparent 40px 60px );}In the first example, the stars are subtracted from the stripes. In the second, the stripes are subtracted from the stars.
Like all the othermask component properties,mask-composite takes a comma-separated list of values. Because the property effects how masks are combined, this property is only relevant for multiple mask layers and the number of used values is one less than the number of mask layers.
The last pair of masks is composited first. The previous mask image is then composited with the previous composition.
Continuing with themasked-element example, if we don't explicitly set themask-composite property, it will default toadd for each layer, as if we had set the following:
.masked-element { mask-image: url("alphaImage.png"), linear-gradient(to right, black, transparent), radial-gradient(circle, white 50%, transparent 75%), none, url("#svg-mask"); mask-mode: match-source; mask-position: 0% 0%; mask-origin: border-box; mask-clip: border-box; mask-size: auto; mask-repeat: repeat; mask-composite: add;}In this case, the<mask> element will be composited with thenone layer. Then the radial gradient will be composited with the result of the previous composition, and so on.
Like we saw with all the other component properties, we could have used themask shorthand:
.masked-element { mask: url("alphaImage.png") 0% 0% / auto repeat border-box border-box add match-source, linear-gradient(to right, black, transparent) 0% 0% / auto repeat border-box border-box add match-source, radial-gradient(circle, white 50%, transparent 75%) 0% 0% / auto repeat border-box border-box add match-source, none 0% 0% / auto repeat border-box border-box add match-source, url("#svg-mask") 0% 0% / auto repeat border-box border-box add match-source;}