How to Use CSS mask-composite for Vector Masks
The CSS mask-composite property enables developers to
construct complex clipping paths by combining multiple mask layers using
Boolean operations like union, subtraction, intersection, and exclusion.
Instead of relying on graphics software to merge shapes, you can define
separate vector masks or gradients in CSS and determine how their
overlapping regions render on the screen. This article explains how
mask-composite works, breaks down its core keywords,
highlights the differences between standard and legacy WebKit
implementations, and provides practical code examples.
How Multiple Mask Layers Work
In CSS, the mask-image property accepts multiple
comma-separated values. When you define multiple masks, they stack on
top of each other. The first mask listed resides at the top of the
stack, and subsequent masks sit beneath it.
.element {
mask-image: url('circle.svg'), url('square.svg');
}Without specifying mask-composite, browsers default to
layering the masks over one another, showing the union of both shapes.
The mask-composite property alters this behavior by
applying compositing operations sequentially from the bottom to the top
of the mask stack.
Standard Boolean Operations
The W3C specification defines four primary values for
mask-composite. Each value represents a standard Boolean
logic operation:
add(Union): The default behavior. The source mask is placed over the destination mask. Any pixel covered by either mask will be visible.subtract(Difference): The source mask is removed from the destination mask. Only areas covered by the first mask that do not overlap with the second mask remain visible.intersect(Intersection): Only the overlapping regions between the masks are retained. Any area not covered by both masks is clipped out.exclude(XOR / Symmetric Difference): The overlapping area between the masks is cleared, leaving only the non-overlapping areas of each mask visible.
When chaining more than two masks, you supply a comma-separated list
to mask-composite. Each keyword dictates how that specific
layer composites with the result of the layers beneath it.
Standard vs. WebKit Syntax
Browser implementations differ between the standard W3C specification and the older WebKit engine implementation.
Standard browsers (such as Firefox) recognize the W3C keywords
(add, subtract, intersect,
exclude). Chromium-based browsers and Safari historically
relied on -webkit-mask-composite, which uses Porter-Duff
compositing operators instead of geometric Boolean keywords:
addcorresponds to-webkit-mask-composite: source-over;subtractcorresponds to-webkit-mask-composite: destination-out;(orsource-outdepending on layer order)intersectcorresponds to-webkit-mask-composite: source-in;excludecorresponds to-webkit-mask-composite: xor;
To ensure cross-browser compatibility, define both declarations together.
Practical Implementation
The following example cuts a circle out of a rounded rectangle to create a custom cutout banner:
.cutout-card {
width: 300px;
height: 200px;
background-color: #3498db;
/* Vector and gradient masks */
mask-image:
radial-gradient(circle at 20px 20px, transparent 20px, black 21px),
linear-gradient(black, black);
/* WebKit compatibility */
-webkit-mask-image:
radial-gradient(circle at 20px 20px, transparent 20px, black 21px),
linear-gradient(black, black);
-webkit-mask-composite: source-in;
/* Standard Boolean masking */
mask-composite: intersect;
}In this implementation, the intersect operation ensures
that only regions common to both the radial mask and the rectangular
linear gradient are visible, creating a dynamic punch-hole effect
without altering the underlying HTML structure.