Introduction to clip-path and mask
The CSS properties clip-path and mask-image are two extremely powerful tools for creating advanced visual effects. Although they seem similar, they have different approaches:
- clip-path: Clips an element according to a geometric shape. Areas outside the shape are completely invisible and non-interactive.
- mask-image: Applies a transparency mask based on an image or gradient. Allows smooth transitions between visible and invisible.
In this complete tutorial, we will explore these two properties in depth, with interactive examples you can copy and adapt to your projects.
clip-path is supported by all modern browsers. For mask-image, remember to add the -webkit- prefix for maximum compatibility with Safari.
clip-path: basic shapes
The clip-path property accepts several types of geometric shapes. Here are the main available functions:
circle() and ellipse()
These functions create circular or elliptical shapes. The syntax is simple and intuitive.
Hover me
Hover me
/* Circle: radius from center */
.circle {
clip-path: circle(50%);
}
/* Circle with custom position */
.circle-offset {
clip-path: circle(40% at 30% 50%);
}
/* Ellipse: X radius, Y radius */
.ellipse {
clip-path: ellipse(50% 35% at 50% 50%);
}
/* Smooth transition on hover */
.circle, .ellipse {
transition: clip-path 0.4s ease;
}
polygon() for complex shapes
The polygon() function allows creating any shape by defining a series of points. Each point is defined by its X and Y coordinates in percentages.
Hover
Hover
Hover
/* Triangle: 3 points */
.triangle {
clip-path: polygon(
50% 0%, /* top */
0% 100%, /* bottom left */
100% 100% /* bottom right */
);
}
/* Hexagon: 6 points */
.hexagon {
clip-path: polygon(
25% 0%, 75% 0%,
100% 50%,
75% 100%, 25% 100%,
0% 50%
);
}
/* 5-pointed star: 10 points */
.star {
clip-path: polygon(
50% 0%, 61% 35%, 98% 35%,
68% 57%, 79% 91%, 50% 70%,
21% 91%, 32% 57%,
2% 35%, 39% 35%
);
}
inset() for rounded rectangles
The inset() function creates a rectangle with inner margins and supports rounded corners.
with border-radius
/* Syntax: inset(top right bottom left round radius) */
.inset-basic {
clip-path: inset(10%);
}
/* With rounded corners */
.inset-rounded {
clip-path: inset(10% 10% 10% 10% round 20px);
}
/* Differentes marges */
.inset-custom {
clip-path: inset(5% 20% 15% 10% round 50px);
}
Use Clippy to generate your clip-path polygons visually. It's much easier than calculating the coordinates manually!
clip-path: path() for complex shapes
For even more elaborate shapes, the path() function accepts an SVG path string. This allows creating Bezier curves and organic shapes impossible with polygon.
/* Heart shape with SVG path */
.heart {
clip-path: path('M 50,30 C 20,0 0,30 50,60 C 100,30 80,0 50,30 Z');
}
/* Water drop shape */
.drop {
clip-path: path('M 50,0 C 70,30 90,50 90,70 C 90,90 70,100 50,100 C 30,100 10,90 10,70 C 10,50 30,30 50,0 Z');
}
/* Alternative: use an external SVG reference */
.custom-shape {
clip-path: url(#myClipPath);
}
The path() function uses absolute units (pixels). For responsive design, prefer polygon() with percentages or use a referenced SVG with url().
mask-image with gradients
Unlike clip-path which cuts sharply, mask-image allows smooth transitions thanks to gradients. Black areas of the mask are opaque, white areas are transparent.
Fade with linear-gradient
/* Fade to bottom */
.fade-bottom {
-webkit-mask-image: linear-gradient(
to bottom,
black 50%,
transparent 100%
);
mask-image: linear-gradient(
to bottom,
black 50%,
transparent 100%
);
}
/* Radial fade from center */
.fade-radial {
-webkit-mask-image: radial-gradient(
circle at center,
black 30%,
transparent 70%
);
mask-image: radial-gradient(
circle at center,
black 30%,
transparent 70%
);
}
/* Horizontal fade on both sides */
.fade-sides {
-webkit-mask-image: linear-gradient(
to right,
transparent,
black 20%,
black 80%,
transparent
);
mask-image: linear-gradient(
to right,
transparent,
black 20%,
black 80%,
transparent
);
}
Mask with image or SVG
You can also use a PNG image with transparency or an SVG as a mask.
/* Mask with external image */
.mask-png {
-webkit-mask-image: url('mask-shape.png');
mask-image: url('mask-shape.png');
-webkit-mask-size: cover;
mask-size: cover;
-webkit-mask-repeat: no-repeat;
mask-repeat: no-repeat;
}
/* Mask with inline SVG (data URI) */
.mask-text {
-webkit-mask-image: url("data:image/svg+xml,%3Csvg...");
mask-image: url("data:image/svg+xml,%3Csvg...");
}
/* Combine multiple masks */
.mask-combo {
-webkit-mask-image:
linear-gradient(black, transparent),
radial-gradient(black 50%, transparent 50%);
-webkit-mask-composite: intersect;
}
clip-path animations
One of the most interesting aspects of clip-path is that it is animatable. You can create smooth transitions between different shapes, provided they have the same number of points.
Reveal effects on hover
Here are three variants of reveal effects you can apply to images or cards.
/* HTML Structure */
/* <div class="reveal">
<img src="image.jpg">
<div class="overlay">Texte</div>
</div> */
/* Revelation circulaire */
.reveal-circle .overlay {
clip-path: circle(100% at 50% 50%);
transition: clip-path 0.5s ease;
}
.reveal-circle:hover .overlay {
clip-path: circle(0% at 50% 50%);
}
/* Left to right reveal */
.reveal-left .overlay {
clip-path: inset(0 0 0 0);
transition: clip-path 0.5s ease;
}
.reveal-left:hover .overlay {
clip-path: inset(0 100% 0 0);
}
/* Revelation diagonale */
.reveal-diagonal .overlay {
clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%);
transition: clip-path 0.5s ease;
}
.reveal-diagonal:hover .overlay {
clip-path: polygon(100% 0, 100% 0, 100% 100%, 100% 100%);
}
Looping morphing animation
Create an animation that continuously transforms one shape into another.
/* Morphing between multiple shapes */
.morph-shape {
animation: morphShape 4s ease-in-out infinite;
}
@keyframes morphShape {
0%, 100% {
/* Diamond */
clip-path: polygon(
50% 0%, 100% 50%,
50% 100%, 0% 50%
);
}
25% {
/* Rectangle */
clip-path: polygon(
0% 0%, 100% 0%,
100% 100%, 0% 100%
);
}
50% {
/* Hexagon (4 points to match) */
clip-path: polygon(
25% 0%, 75% 0%,
75% 100%, 25% 100%
);
}
75% {
/* Circle via polygon */
clip-path: circle(50%);
}
}
/* Pulse animation with circle */
.pulse-circle {
animation: pulseReveal 3s ease-in-out infinite;
}
@keyframes pulseReveal {
0%, 100% {
clip-path: circle(30% at 50% 50%);
}
50% {
clip-path: circle(70% at 50% 50%);
}
}
For transitions between polygon() to work, both shapes must have exactly the same number of points. Otherwise, there will be no smooth interpolation.
Creative effects and use cases
Let's now look at some concrete applications of clip-path and mask in real projects.
Image gallery with overlay
.gallery-item {
position: relative;
overflow: hidden;
cursor: pointer;
}
.gallery-item img {
width: 100%;
transition: transform 0.4s;
}
.gallery-item .overlay {
position: absolute;
inset: 0;
background: rgba(0, 0, 0, 0.7);
display: flex;
align-items: center;
justify-content: center;
/* Commence invisible */
clip-path: circle(0% at 50% 50%);
transition: clip-path 0.4s ease;
}
.gallery-item:hover .overlay {
clip-path: circle(100% at 50% 50%);
}
.gallery-item:hover img {
transform: scale(1.1);
}
Cards with diagonal cutout
.diagonal-card {
position: relative;
background: #12121a;
border-radius: 16px;
overflow: hidden;
}
.diagonal-card::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 100%;
background: linear-gradient(135deg, #6366f1, #8b5cf6);
/* Diagonal cut */
clip-path: polygon(
0 0, /* top left */
100% 0, /* top right */
100% 30%, /* middle right */
0 60% /* middle left */
);
}
.diagonal-card-content {
position: relative;
padding: 80px 20px 20px;
}
Best practices
To conclude, here are some recommendations for using clip-path and mask effectively:
Performance
- Favor simple shapes: circle, ellipse and inset are more performant than polygon with many points
- Use
will-change: clip-pathif you frequently animate an element - Avoid animations on mobile for very complex shapes
Accessibility
- Clipped content remains accessible to screen readers, keep that in mind
- Respect prefers-reduced-motion for animations
@media (prefers-reduced-motion: reduce) {
.animated-shape,
.reveal-overlay,
.morph-shape {
animation: none;
transition: none;
}
}
Compatibility
- clip-path: Supported by all modern browsers
- mask-image: Always add the
-webkit-prefix - path(): Limited support, prefer polygon or url()
Conclusion
The clip-path and mask-image properties open a world of creative possibilities in CSS. Whether you want to create geometric shapes, hover reveal effects or morphing animations, these tools are indispensable in your front-end developer toolkit.
Don't hesitate to experiment with values and combine these techniques with other CSS properties like filters or transforms for even more spectacular results.
Discover our collection of ready-to-use CSS effects with many examples using clip-path and mask.