Masks
Purpose and Scope
Mask utilities control how an element is visually clipped or revealed by a mask layer. In Tailwind CSS, the mask family is part of the effects documentation area and uses utility classes for CSS properties such as mask-size, mask-clip, and mask-composite. This page is a focused reference for applying masks in application markup, especially when composing a mask image with background images, multiple mask layers, and responsive variants. It is intended for developers who already understand Tailwind’s utility-first model and want a single place to compare the mask APIs and choose the correct class family for a visual effect.
Masks are different from opacity utilities and from clipping utilities. Opacity changes the transparency of the entire element, while a CSS mask uses an image or gradient as an alpha or luminance map that determines which parts of the element are visible. Tailwind’s mask utilities expose common CSS mask property values as readable class names, and arbitrary values let you provide URLs, gradients, positions, sizes, and multi-layer settings without leaving the utility workflow. A typical masked hero image combines a mask image utility with a background image utility and then adjusts sizing, clipping, or composition with additional mask classes.
The official mask reference is split across individual property pages. mask-size documents sizing classes like mask-cover, mask-contain, and mask-auto, including arbitrary value forms such as mask-size-[auto_100px] and custom-property shorthand like mask-size-(--my-mask-size). mask-clip documents bounding-box classes such as mask-clip-border, mask-clip-padding, and mask-clip-content. mask-composite documents how multiple masks combine through mask-add, mask-subtract, mask-intersect, and mask-exclude. This wiki page groups those related APIs so you can reason about the whole mask layer instead of jumping between property pages.
Relevant Source Files
packages/@tailwindcss-upgrade/src/codemods/css/migrate-media-screen.ts- Implements the upgrade codemod that rewrites legacy responsive screen syntax into modern media queries, which matters when mask utilities are used inside responsive CSS during v4 migration.packages/@tailwindcss-upgrade/src/codemods/css/migrate-media-screen.test.ts- Verifies the migration behavior for built-in screens, custom min and max screens, min/max ranges, raw media queries, and legacy@screensyntax.
Sources: packages/@tailwindcss-upgrade/src/codemods/css/migrate-media-screen.ts, packages/@tailwindcss-upgrade/src/codemods/css/migrate-media-screen.test.ts
Core Mask Primitives
A mask layer usually starts with a mask image. Tailwind supports arbitrary mask values, so an element can use a URL-based mask such as mask-[url(/img/scribble.png)] or a more specialized arbitrary declaration when you need a precise CSS value. The official examples pair these mask image utilities with background images, for example a masked element using mask-[url(/img/scribble.png)] and bg-[url(/img/mountains.jpg)]. This pattern is useful because the background supplies the visible artwork and the mask supplies the shape or transparency channel that reveals it.
mask-size determines how the mask image is scaled within the mask positioning area. Use mask-cover when the mask should fill the layer even if that means cropping, mask-contain when the entire mask image should remain visible without cropping or stretching, and mask-auto when the browser should use the mask image’s intrinsic dimensions. For unusual layouts, mask-size-[<value>] accepts a custom CSS value, and mask-size-(<custom-property>) is shorthand for wrapping a custom property in var(). The custom-property form is especially convenient when design tokens or component variables control mask behavior.
mask-clip defines the bounding box for the mask. The common box values mirror CSS layout boxes: mask-clip-border, mask-clip-padding, and mask-clip-content clip the mask relative to the border box, padding box, or content box. SVG-oriented values such as mask-clip-fill, mask-clip-stroke, and mask-clip-view are available when the mask participates in SVG rendering contexts. mask-no-clip maps to mask-clip: no-clip, which prevents the mask from being clipped to a specific box. Choose the clip utility after deciding whether borders and padding should be part of the masked area.
mask-composite matters when an element has more than one mask layer. The official examples use comma-separated mask URLs and positions, then switch the compositing behavior with mask-add, mask-subtract, mask-intersect, or mask-exclude. These classes do not define the mask images themselves; they define how multiple masks combine. For example, mask-intersect keeps only overlapping mask regions, while mask-exclude removes overlapping areas. When debugging multi-layer masks, first confirm each layer’s image, position, and size, then change the composite utility to verify the final boolean operation.
Compact Utility Reference
| Family | Utilities | CSS property or behavior |
|---|---|---|
| Mask image | mask-[url(...)], mask-[<value>] | Supplies the mask image or arbitrary mask-related value. |
| Mask size | mask-auto, mask-cover, mask-contain | Sets mask-size to auto, cover, or contain. |
| Custom mask size | mask-size-[<value>], mask-size-(<custom-property>) | Sets mask-size from an arbitrary value or CSS custom property. |
| Mask clip | mask-clip-border, mask-clip-padding, mask-clip-content | Clips the mask to border, padding, or content boxes. |
| SVG mask clip | mask-clip-fill, mask-clip-stroke, mask-clip-view | Uses SVG fill, stroke, or view boxes. |
| No clipping | mask-no-clip | Sets mask-clip: no-clip. |
| Mask composite | mask-add, mask-subtract, mask-intersect, mask-exclude | Controls how multiple mask layers are combined. |
This reference is intentionally property-oriented. In real components, these classes are usually combined. A card might use a URL mask, mask-cover, and mask-clip-padding so the image fills the available area but respects padding. A decorative blend might use two mask images, explicit positions, and mask-subtract to cut one shape out of another. A responsive layout might start with mask-auto on small screens and switch to md:mask-contain when there is enough space for the full mask artwork. The utility family is most powerful when each class describes one decision in the mask layer.
Examples and Composition Patterns
Use mask-cover when the mask shape should always fill the available space. This is often the right choice for decorative textures or rough-edge image treatments where preserving every pixel of the mask is less important than avoiding empty areas. The tradeoff is cropping: if the mask aspect ratio differs from the element, the browser may crop parts of the mask layer. In Tailwind markup, that decision is visible directly on the element, so reviewers can see that the component favors coverage over complete mask visibility.
<div class="mask-cover mask-[url(/img/scribble.png)] bg-[url(/img/mountains.jpg)]">
<!-- masked image treatment -->
</div>Use mask-contain when the entire mask image needs to remain visible. This is a better fit for logos, badges, framed illustrations, or mask assets with important edges. mask-auto is the neutral choice when the mask asset already has the desired intrinsic size and the element should not scale it. For precise one-off values, the arbitrary syntax keeps the rule colocated with the element: mask-size-[auto_100px] can express a two-axis size without adding a separate CSS selector, and mask-size-(--my-mask-size) lets a component variable drive the value.
Multi-layer masks require careful ordering. The CSS value for the mask image can contain multiple comma-separated layers, and related values such as position can also be comma-separated. Tailwind’s arbitrary value syntax can express those values, while the compositing class determines how the layers combine. A useful debugging workflow is to begin with mask-add, verify the layer positions, and then switch to mask-subtract, mask-intersect, or mask-exclude. If the result disappears unexpectedly, test each mask layer independently before adjusting the composite operation.
<div class="mask-intersect mask-[url(/img/circle.png),url(/img/circle.png)] mask-[position:30%_50%,70%_50%] bg-[url(/img/mountains.jpg)]">
<!-- overlapping masks are intersected -->
</div>Responsive and Upgrade Behavior
Mask utilities support Tailwind’s normal variant composition, so a breakpoint prefix can be added to change mask behavior at different viewport sizes. The official mask pages show examples such as mask-auto md:mask-contain, mask-clip-border md:mask-clip-padding, and mask-add md:mask-subtract. Those examples follow the same responsive model as other utility families: the unprefixed class applies by default, while the prefixed class applies at the named breakpoint and above. This keeps responsive mask changes close to the component markup instead of requiring separate media-query blocks.
The upgrade package includes a codemod for CSS that still uses legacy screen syntax. The migrateMediaScreen plugin resolves configuration with the current design system, creates a lookup for screen names, rewrites @screen md to @media screen(md), and then replaces screen(...) functions inside media at-rules with concrete media queries. For string breakpoints it emits a modern breakpoint expression using theme(--breakpoint-<name>); for object-based screens it delegates to the compatibility screen media-query builder. Sources: packages/@tailwindcss-upgrade/src/codemods/css/migrate-media-screen.ts
The accompanying tests show the migration expectations that matter for responsive mask code living in CSS files. Built-in breakpoints and custom string or object min-width screens become width-range media queries, max-width screens become inverse range expressions, combined min and max screens become bounded ranges, and raw screen definitions remain raw media queries. That means a CSS block containing mask utilities or custom mask declarations inside legacy @screen syntax should retain its responsive intent after migration, even though the source syntax changes. Sources: packages/@tailwindcss-upgrade/src/codemods/css/migrate-media-screen.test.ts
Implementation Notes for Application Code
For application authors, the most important constraint is that mask utilities map to browser CSS mask features. If a visual effect relies on a specific mask image, check the final generated CSS and browser support for the exact property combination you are using. The Tailwind class names make the CSS intent compact, but they do not change the underlying behavior of mask-size, mask-clip, or mask-composite. When a mask is not visible, inspect the element’s dimensions, the referenced image URL, the background being revealed, and whether multiple mask layers are being combined as expected.
Prefer semantic component variables when the same mask tuning appears in multiple places. For example, a design system could expose --card-mask-size and use mask-size-(--card-mask-size) in shared components, allowing themes or responsive containers to adjust the value without rewriting class lists. For single-use artwork, arbitrary values are more direct and keep the implementation local. In both cases, pair mask utilities with variants deliberately: responsive prefixes should describe layout-driven changes, while state variants should describe interaction-driven changes such as hover treatments.
Next Steps
Read the broader effects references when mask behavior overlaps with shadows, opacity, blend modes, filters, or backdrop filters. If you are migrating an older Tailwind project, also review the upgrade guide and responsive design pages so legacy @screen usage and breakpoint-based mask changes are handled consistently. For everyday usage, start with the property-specific decision: choose the mask image, choose the size strategy, choose the clipping box, then add compositing only when you have multiple mask layers.