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:

  • add corresponds to -webkit-mask-composite: source-over;
  • subtract corresponds to -webkit-mask-composite: destination-out; (or source-out depending on layer order)
  • intersect corresponds to -webkit-mask-composite: source-in;
  • exclude corresponds 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.