CSS clip-path and Masking Explained
clip-path and mask-image clip or fade elements into custom shapes in pure CSS, replacing image editors and SVG sprites for cropping.
clip-path and mask-image are CSS properties that cut or fade an element down to a custom shape, entirely in the stylesheet. No image editor, no SVG sprite sheet, no extra wrapper element required. clip-path gives you a hard-edged boundary — anything outside the shape simply isn’t painted. mask-image is more flexible: it can produce soft, gradient edges by using the alpha channel or luminance of an image, gradient, or SVG as a stencil.
clip-path: hard-edged shapes
clip-path accepts a handful of basic shape functions, each defining a region relative to the element’s box:
.badge {
clip-path: circle(50% at center);
}
.ribbon {
clip-path: polygon(0 0, 100% 0, 100% 75%, 50% 100%, 0 75%);
}
.card {
clip-path: inset(10px 20px 10px 20px round 8px);
}
circle(radius at position)— a circular clip, useful for avatars or spotlight reveals.ellipse(rx ry at position)— an elliptical variant.inset(top right bottom left round radius)— trims edges inward, optionally with rounded corners.polygon(x1 y1, x2 y2, ...)— an arbitrary straight-edged shape, defined as a list of coordinate pairs. This is how you get angled banners, chevrons, and diagonal section dividers without a background image.
Everything outside the shape is clipped away — it doesn’t just become invisible, it stops taking up interactive space too, so clicks and hovers outside the shape pass through to whatever’s behind it.
Referencing an SVG <clipPath>
For shapes more complex than the basic functions allow, point clip-path at an SVG clipPath element by URL:
<svg width="0" height="0">
<clipPath id="blob" clipPathUnits="objectBoundingBox">
<path d="M0.5,0 C0.8,0 1,0.2 1,0.5 ..." />
</clipPath>
</svg>
.hero-image {
clip-path: url(#blob);
}
This is the escape hatch for organic, hand-drawn blob shapes — common in marketing hero sections — that would be painful to express as a polygon().
mask-image: soft edges
Where clip-path gives you a binary in-or-out boundary, mask-image uses the mask source’s alpha (or luminance) as a gradient of visibility. A linear-gradient mask is the classic use case: fading an image or block of text into transparency at one edge.
.fade-out {
mask-image: linear-gradient(to bottom, black 60%, transparent 100%);
}
Fully opaque areas of the mask show the element at full opacity; fully transparent areas hide it completely; everything in between blends smoothly. You can also mask with a PNG, an SVG, or radial-gradient() for vignette-style effects.
Multiple mask layers can be combined with mask-composite, similar to how background-image supports layered backgrounds — useful for combining a shape mask with a gradient fade in one declaration.
clip-path vs mask-image
clip-path | mask-image | |
|---|---|---|
| Edge quality | Hard, geometric | Can be soft or gradient |
| Source | Basic shapes, SVG clipPath, URL | Images, gradients, SVG |
| Performance | Cheap — geometry only | Slightly heavier — image compositing |
| Hit testing | Clipped area is non-interactive | Masked-out area is still hidden, but historically less consistent across browsers for pointer events |
| Typical use | Badges, banners, angled dividers | Fades, vignettes, image cutouts |
Reach for clip-path when you need a crisp geometric boundary and want the cheapest possible paint cost. Reach for mask-image when the edge itself needs to fade or follow a raster/vector image rather than a simple polygon.
Animating clip-path
Because clip-path describes a shape as a list of numeric values, browsers can interpolate between two shapes of the same type and point count to animate the transition:
.reveal {
clip-path: circle(0% at 50% 50%);
transition: clip-path 0.4s ease-out;
}
.reveal.is-open {
clip-path: circle(150% at 50% 50%);
}
This produces a smooth circular reveal without JavaScript-driven layout changes — a common pattern for image galleries and modal transitions, and a nice complement to the View Transitions API when you want a shaped wipe rather than a plain cross-fade. Animating polygon() shapes works the same way, as long as both keyframes list the same number of points; browsers can’t interpolate between shapes with a different point count.
Both properties are cheaper to animate than changing width, height, or clip: rect() (the old, deprecated clipping property), because they don’t trigger layout — only compositing. That makes them a good fit alongside other layout-friendly techniques covered in our Core Web Vitals guide.
Combining with container queries and grid
clip-path shapes defined in percentages scale naturally with the element’s box, which pairs well with responsive layouts built on CSS Grid or sized with container queries — the clip recalculates automatically as the container resizes, with no extra media-query bookkeeping.
Browser support and fallbacks
Both properties have solid support in current evergreen browsers for the basic shape functions and gradient masks; SVG-referenced clip paths and layered masks are the parts most likely to need a fallback check on older engines. Because a missing clip-path or mask-image simply degrades to “no clipping” rather than broken layout, both are safe to use progressively — design the unclipped state to look acceptable on its own, then layer the shape on top.
The takeaway
clip-path cuts an element to a hard-edged shape — circles, polygons, insets, or an SVG path — cheaply and with animatable geometry. mask-image fades an element using the alpha or luminance of a gradient, image, or SVG, which is what you want for soft edges and vignettes. Both skip the need for pre-cropped image assets, and both animate on the compositor rather than triggering layout, making them a low-cost way to add shaped reveals and transitions to a page.
Tagged
Keep reading
Takina · · 4 min read CSS object-fit and object-position, Explained
object-fit controls how an image or video is cropped inside its box, and object-position controls which part of it stays visible. How they work together.
Takina · · 5 min read CSS inherit, initial, unset & revert Explained
CSS's four global keywords control where a property's value comes from. How inherit, initial, unset, and revert differ, with a comparison table.
Takina · · 4 min read Dynamic Viewport Units: dvh, svh, and lvh Explained
dvh, svh, and lvh fix the classic mobile vh bug where browser toolbars cut off full-height layouts. Here's what each unit measures and when to use it.