What is CSS clip-path?

The clip-path CSS property defines a clipping region on an element. Anything inside the region is visible. Anything outside is hidden — completely removed from the painted output, not just transparent. Unlike overflow: hidden which clips to a rectangle, clip-path can clip to any shape including triangles, pentagons, hexagons, and complex custom polygons.

An important distinction: elements clipped with clip-path still occupy their layout space. The clipping is purely visual — neighbouring elements still see the original dimensions. If you need the layout to collapse around a clip, you also need to adjust the element's dimensions separately.

Triangle · Pentagon · Hexagon — all using polygon()

The Four Shape Functions

clip-path supports four CSS basic shape functions, plus the ability to reference SVG <clipPath> elements for complex curves. Here is what each function does:

FunctionShapeUse case
polygon()Any polygon with n verticesAngled sections, custom shapes, icons
circle()Circle with a radius and centreProfile images, avatar masks, circle reveals
ellipse()Ellipse with rx, ry and centreOval crops, organic masks
inset()Rectangle with optional round cornersInner cropping, reveal animations

polygon() — Custom Shapes

polygon() takes any number of coordinate pairs as percentages of the element's width and height. The browser connects them in order to form the clipping polygon. Minimum is 3 points (triangle); there is no practical maximum.

CSS
/* Triangle pointing up */
clip-path: polygon(50% 0%, 0% 100%, 100% 100%);

/* Angled hero section — parallelogram-style bottom */
clip-path: polygon(0 0, 100% 0, 100% 85%, 0 100%);

/* Angled from top-right */
clip-path: polygon(0 0, 100% 0, 100% 100%, 0 90%);

/* Diamond */
clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);

/* Arrow pointing right */
clip-path: polygon(0 20%, 70% 20%, 70% 0%, 100% 50%, 70% 100%, 70% 80%, 0 80%);

/* Hexagon */
clip-path: polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0% 50%);
Angled section · Diamond · Arrow

circle() and ellipse()

circle(radius at x y) clips to a circle. ellipse(rx ry at x y) clips to an ellipse. Both are much simpler than polygon() for circular cropping — the go-to technique for profile image circles in CSS without needing border-radius:

CSS
/* Circle crop on an image */
.avatar {
  clip-path: circle(50% at center);
  /* Same result as border-radius: 50% but clips child content too */
}

/* Spotlight effect — circle from off-centre */
.spotlight {
  clip-path: circle(60% at 30% 40%);
}

/* Expanding circle reveal animation */
.reveal {
  clip-path: circle(0% at 50% 50%);
  transition: clip-path 0.6s ease;
}
.reveal.active {
  clip-path: circle(150% at 50% 50%);
}

/* Ellipse crop */
.oval-image {
  clip-path: ellipse(50% 40% at center);
}

inset() — Rectangular Clips with Rounded Corners

inset() clips to a rectangle defined by inset distances from the element's edges. It supports the round keyword to add border-radius to the clip. It is the right choice for reveal animations where a rectangle expands or contracts:

CSS
/* Clip 20px from all sides */
clip-path: inset(20px);

/* Different values per side: top right bottom left */
clip-path: inset(10px 20px 30px 20px);

/* Rounded corners */
clip-path: inset(0 round 16px);

/* Wipe-in reveal animation */
.wipe-reveal {
  clip-path: inset(0 100% 0 0); /* fully hidden: right edge at left */
  transition: clip-path 0.6s ease;
}
.wipe-reveal.active {
  clip-path: inset(0 0 0 0); /* fully shown */
}

Animating clip-path

clip-path is animatable, but with one critical constraint: the shape function and the number of polygon points must match in both keyframes. You cannot animate from a circle() to a polygon(), and you cannot animate between polygons with different numbers of vertices. The browser interpolates point positions, so both shapes must have the same structure.

CSS
/* ✅ Works — same function, same point count */
@keyframes morph {
  from { clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%); }
  to   { clip-path: polygon(10% 10%, 90% 5%, 95% 90%, 5% 95%); }
}

/* ✅ Circle reveal */
@keyframes reveal {
  from { clip-path: circle(0% at 50% 50%); }
  to   { clip-path: circle(150% at 50% 50%); }
}

/* ❌ Won't animate — different functions */
@keyframes broken {
  from { clip-path: circle(50%); }
  to   { clip-path: polygon(0 0, 100% 0, 100% 100%); }
}

/* Hover shape morph */
.shape {
  clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%);
  transition: clip-path 0.4s ease;
}
.shape:hover {
  clip-path: polygon(10% 10%, 90% 5%, 95% 90%, 5% 95%);
}

Real-World Use Cases

Angled hero sections

CSS
.hero {
  clip-path: polygon(0 0, 100% 0, 100% 88%, 0 100%);
  background: linear-gradient(135deg, #7c6fff, #ff6fb0);
  min-height: 70vh;
}

/* Opposite angle */
.hero-reverse {
  clip-path: polygon(0 0, 100% 0, 100% 100%, 0 88%);
}

Custom image shapes

CSS
/* Hexagon image crop */
.hex-image {
  clip-path: polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0% 50%);
}

/* Diagonal crop */
.diag-image {
  clip-path: polygon(0 0, 100% 0, 80% 100%, 0 100%);
}

clip-path vs overflow: hidden

clip-pathoverflow: hidden
ShapeAny CSS shapeRectangle only
AnimatableYes (matching shapes)Not practically
Affects layoutNoYes (hides scrollbar content)
Child elementsClipped visuallyClipped visually
PerformanceRepaint (use will-change)Cheap

Browser Support

clip-path with basic shapes (polygon, circle, ellipse, inset) is supported in all modern browsers. The path() function for SVG path syntax has growing support (Chrome 88+, Firefox 97+, Safari 13.1+).

Create clip-path shapes without writing coordinates

Drag control points, choose presets, preview on real images. Copy the CSS in one click.

Open Clip Path Generator →