Blog / CSS

CSS clip-path and mask: Complete Guide to Creative Reveals

Discover how to use clip-path and mask-image to create custom shapes, spectacular reveal effects and smooth animations. Master these powerful CSS properties with concrete examples.

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.

💡
Browser support

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.

Circle
Hover me
Ellipse
Hover me
circle-ellipse.css
/* 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.

Triangle
Hover
Hexagon
Hover
Star
Hover
polygon-shapes.css
/* 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.

Inset
with border-radius
inset.css
/* 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);
}
🔧
Recommended tool

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.

clip-path-svg.css
/* 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);
}
⚠️
path() limitation

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

mask-gradients.css
/* 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-image-svg.css
/* 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.

HOVER
HOVER
HOVER
reveal-effects.css
/* 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.

morph-animation.css
/* 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%);
  }
}
⚠️
Important rule for animations

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-overlay.css
.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

Feature Card
With a diagonal header
diagonal-card.css
.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-path if 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
accessibility.css
@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.

🎨
Go further

Discover our collection of ready-to-use CSS effects with many examples using clip-path and mask.