mask-image in CSS: Freeform Shapes and Soft Transitions Without Hand-Drawn SVGs
AI generated
{ }
@
CSS · Masks · Image Design · Layout
mask-image in CSS
Freeform shapes and soft edges without translating every pixel into an SVG polygon

mask-image masks an element through a gradient or image file with stepless transparency, instead of only clipping it hard and geometrically like clip-path. That makes the property the right tool for frayed product images, organic hero areas, and a reusable icon system that needs no extra SVG exports at all.

14 min read mask-image · mask-composite · mask-mode Chrome · Firefox · Safari · Edge

1. What mask-image does and why CSS masks go beyond clip-path

With mask-image, an element can be masked by a gradient or an image file instead of merely being clipped into a rectangle or polygon. Unlike clip-path, which always produces a hard, geometrically defined edge, a CSS mask can make every pixel of an element individually transparent, semi transparent, or fully visible, depending on the brightness or alpha channel of the mask source. That is the decisive difference: mask-image understands intermediate values, a clip path only understands on or off.

In practice that means a product photo can fade softly at its edge, a hero section can end in an organic shape instead of a rectangle, and an icon can pick up the exact outline of a PNG file with an alpha channel, without anyone manually translating that outline into a polygon. The browser calculates directly from the mask source which pixels stay visible, which is far less maintenance than a hand maintained SVG path once an asset's shape changes later on.

2. Basic syntax: mask-image with gradients and image files

The simplest form of mask-image accepts either an image URL or one of the familiar gradient functions as its value. A linear-gradient from opaque to transparent creates a soft transition at an edge, a radial-gradient creates a circular cutout in the middle, and a PNG or SVG file with an alpha channel takes over its exact transparency curve as the element's mask. On top of that, mask-size, mask-position and mask-repeat control placement exactly the way background-size, background-position and background-repeat do for background images.

The default value of mask-mode is match-source, which lets the browser automatically decide, for an SVG, whether the luminance or the alpha channel serves as the mask, depending on what the file provides. For bitmap images like PNG or WebP the alpha channel usually applies, while for pure gradients the brightness of every pixel directly determines opacity: white means fully visible, black means fully hidden, and every shade of gray in between yields a proportional transparency of the underlying element.


/* Soft fade at the bottom image edge */
.hero-image {
  mask-image: linear-gradient(to bottom, black 60%, transparent 100%);
  mask-size: 100% 100%;
  mask-repeat: no-repeat;
}

/* Outline of a PNG file with alpha channel used as a mask */
.product-thumb {
  mask-image: url("/media/masks/torn-edge.svg");
  mask-mode: alpha;
  mask-size: cover;
}

3. Cutting freeform shapes: radial and conic gradients as a mask

A radial-gradient used as a mask source produces a circular or elliptical cutout whose edge can be as hard or as soft as needed, depending on how close together the color stops sit. A conic-gradient goes a step further and allows segmented shapes that read like a pie chart, useful for badge elements that should only reveal a specific angular slice of an image. Both gradient types can also be combined by listing several mask sources, comma separated, inside mask-image.

The big advantage over a hand drawn SVG shape is that a gradient is described purely mathematically and behaves responsively without a path having to be recalculated at every breakpoint. A freeform shape that looks good at 1200 pixels wide works exactly the same at 400 pixels, because mask-size scales relative to the box. For organic, irregular edges that no gradient can represent cleanly, an SVG mask file remains the better choice, but for most freeform needs in a shop layout a well tuned gradient is entirely sufficient.


/* Segmented badge shape via a conic gradient */
.badge-freeform {
  mask-image: conic-gradient(black 0deg 270deg, transparent 270deg 360deg);
  mask-size: 100% 100%;
}

/* Softly fading spotlight effect */
.spotlight {
  mask-image: radial-gradient(circle at 30% 40%, black 0%, black 55%, transparent 80%);
}

4. Soft transitions at image edges: fade-out effects without extra markup

A classic use case for mask-image is softly fading out an image at one or more edges, for example so a product photo blends seamlessly into the page's background color instead of ending with a visible edge. A linear gradient running from opaque black to transparent is already enough, and it needs no extra image asset, no Photoshop export, and no additional DOM element, since it works directly in CSS.

For a transition on several edges at once, say top and bottom for an infinite looking carousel, two gradients can be combined inside a single mask-image declaration by listing them comma separated and blending them together with mask-composite. This technique reliably replaces older solutions using semi transparent overlay divs, which added extra markup and extra stacking context complexity to a layout that only ever needed a soft edge.


/* Fade on all four edges of a carousel */
.fade-carousel {
  mask-image:
    linear-gradient(to right, transparent, black 10%, black 90%, transparent),
    linear-gradient(to bottom, transparent, black 15%, black 85%, transparent);
  mask-composite: intersect;
}

5. mask-image vs. clip-path: hard edges against soft gradients

clip-path defines a geometric shape, usually through polygons, circles, or ellipses, and every pixel inside that shape is either fully visible or fully invisible. That produces sharp, precise edges, works great for geometric layouts like diagonally cut sections, and is computationally cheap because the browser only has to run a path calculation, not a per pixel opacity calculation.

mask-image, on the other hand, understands any number of intermediate opacity steps and therefore fits anything meant to look soft, organic, or photographic. The practical rule of thumb: reach for clip-path for a straight or gently curved edge, reach for mask-image for a gradient, a texture based cutout, or a frayed outline. Both properties can also be applied to the same element at once, when both a hard outer shape and a soft inner gradient are wanted.

6. Combining multiple masks: mask-composite and mask-mode working together

Once more than one mask source is involved, mask-composite determines how the individual masks are blended: add unions the visible areas, subtract removes one mask from another, intersect leaves only the shared visible area, and exclude shows only the areas that do not overlap. These four modes map exactly onto the classic boolean operations from vector graphics and allow complex shapes without a single extra SVG file.

A practical example is a ring built from two overlapping circles: a large, opaque circle as the first mask and a smaller, equally opaque circle as the second mask with mask-composite: exclude together produce a ring shaped cutout, with no border-radius trickery and no extra pseudo element. It matters here that each mask source can receive its own mask-mode, in case some sources are gradients and others image files with an alpha channel.


/* Ring shape from two overlapping circle masks */
.ring-mask {
  mask-image:
    radial-gradient(circle, black 0 100%),
    radial-gradient(circle, black 0 60%);
  mask-composite: exclude;
}

7. Browser support, prefixes and robust fallback strategies

All current versions of Chrome, Edge, Firefox and Safari now support the unprefixed mask-image property reliably, but Safari still requires the -webkit- variant for some of the composite properties like mask-composite, sometimes with slightly different value names. A robust setup therefore declares the prefixed variant first and the standardized one right after, so modern browsers pick up the second declaration while older WebKit versions fall back to the first.

For browsers that do not support mask-image at all, the element should still remain functional and readable without the mask, for example by making sure the mask only affects a decorative edge and never hides information required for the content. An @supports query makes that safeguard explicit: the unmasked state is the baseline, the mask is a progressive enhancement on top of it, never a prerequisite for content to be visible at all.


.fade-edge {
  -webkit-mask-image: linear-gradient(to bottom, black 70%, transparent);
  mask-image: linear-gradient(to bottom, black 70%, transparent);
}

@supports not (mask-image: linear-gradient(black, transparent)) {
  .fade-edge {
    mask-image: none;
    -webkit-mask-image: none;
  }
}

8. Performance and rendering: what to watch for with complex masks

A CSS mask forces the browser to render the element on a separate compositing layer, because opacity has to be recalculated per pixel instead of simply copying the finished element onto the screen. For a single, static mask on a hero image that extra cost is negligible, but once many elements are masked at the same time, or the mask itself is animated, for example through a moving mask-position, the rendering load becomes noticeable.

For animations it therefore helps to keep the mask's size and shape constant and only animate the position, since that lets the browser calculate the mask once and then simply shift it instead of recomputing it. Anyone masking many similar elements, say an entire product tile grid, should also check whether a single, reused mask file referenced by URL is enough, instead of generating an individual inline gradient for every element that the browser has to reparse every time.

9. Practical use in a shop: product images, hero sections and icon systems

In an e-commerce context, mask-image fits three recurring tasks particularly well: softly fading product images on category pages, organically shaped hero areas on the homepage that stand out from the usual rectangle, and a consistent icon system colored from a single SVG sprite file through a mask, instead of exporting a separate SVG for every color variant. The last one in particular saves substantial maintenance effort for icons that need a different accent color per theme or store view.

Implementing this in a Hyvä theme, mask-image can be added through Tailwind utility classes or directly in a CSS layer without needing any extra JavaScript. The only thing to keep in mind is treating the mask as a purely decorative element and making sure the underlying content, say a product name or an image's alt text, remains fully intact for screen readers and search engines regardless of the mask.

Technique Edge type Intermediate values Typical use
mask-image (gradient) Soft, freely scalable Yes, stepless transparency Fade effects, organic areas
mask-image (image file) Any, depends on the alpha channel Yes Frayed edges, icon coloring
clip-path (polygon/circle) Hard, geometric No Diagonal sections, geometric layouts
clip-path: shape() Hard, curves possible No Organic but sharp shapes
SVG clipPath/mask Any Yes for mask Complex, reusable shapes

Mironsoft

Modern CSS, layout architecture and rendering performance

CSS that stays maintainable instead of breaking with every change?

We review existing stylesheets for specificity chaos and layout thrashing, then build a CSS architecture with cascade layers, custom properties and modern layout primitives that still makes sense after the tenth feature.

CSS Audit

Systematically uncovering specificity issues, cascade conflicts and unused selectors.

Architecture Refactoring

Introducing cascade layers, custom properties and design tokens cleanly.

Performance Tuning

Fixing layout thrashing, expensive selectors and rendering bottlenecks.

10. Summary

mask-image in CSS: The Essentials at a Glance

Core idea

mask-image masks an element through a gradient or image file with stepless transparency, instead of clipping it hard and geometrically like clip-path.

Multiple masks

mask-composite with add, subtract, intersect or exclude combines several mask sources into complex shapes without a single extra SVG file.

Browser support

The base property runs unprefixed in all current browsers, mask-composite still needs an extra -webkit- declaration in Safari.

Accessibility

Masks stay purely decorative. Alt text and semantic content must remain fully intact for screen readers regardless of the mask.

11. FAQ: mask-image in CSS: The Essentials at a Glance

1What is the difference between mask-image and clip-path?
clip-path produces a hard, geometrically defined edge with no intermediate values. mask-image allows stepless transparency based on a gradient or an image file's alpha channel, making it fit for soft transitions.
2Can I combine several masks on one element?
Yes. Several mask sources are listed comma separated inside mask-image and blended together with mask-composite using add, subtract, intersect or exclude.
3Which image formats work as a mask source?
PNG and WebP with an alpha channel, as well as SVG files, work reliably. The browser picks the alpha or luminance channel as the mask automatically through mask-mode.
4Does mask-image still need vendor prefixes?
Not for the base property in current browsers, but mask-composite still needs the -webkit- variant with sometimes different value names in Safari, so a double declaration is recommended.
5Is mask-image well suited for animations?
Yes, as long as the mask's size and shape stay constant and only the position is animated. Animating the mask shape itself is more expensive and should be used sparingly.
6Does a mask affect an image's accessibility?
Not directly, as long as the mask stays purely decorative. Alt text and semantic content must remain fully intact regardless of the mask so screen readers keep working correctly.
7How does mask-image differ from a simple opacity gradient overlay?
An overlay div sits as an extra element on top of the image and visually covers it, while mask-image controls the actual visibility of the element itself, without extra markup or stacking context complexity.
8What happens if a browser does not support mask-image?
Without an @supports safeguard, the element usually stays either fully invisible or fully visible, depending on the fallback value. A targeted @supports query ensures content always stays readable.
9Can I use mask-image for responsive freeform shapes?
Yes, since gradients scale relative to the box size, a freeform shape created with mask-image automatically works at any screen size without a path needing to be recalculated.
10When should I use an SVG mask file instead?
When the desired shape is too irregular or detailed for a gradient, for example a hand drawn outline or a complex texture, an SVG file with mask-mode: alpha is the more practical solution.