CSS Clip Path
The clip-path property cuts an element into a custom shape. Everything outside the clipping region becomes invisible — the content still exists in the DOM, it just does not render outside the shape. No image editor needed.
How Clipping Works
DIAGRAM — Clipping a rectangle to a circle:
Before clip-path: After clip-path: circle(50%):
┌──────────────────┐ ╭──────────╮
│ │ ╱ ╲
│ Photo content │ │ Photo (round) │
│ │ │ │
└──────────────────┘ ╲ ╱
╰──────────╯
Corners are invisible — the image is still there,
just hidden outside the circle boundary.
clip-path: circle()
Creates a circular clip. The value is the radius as a percentage or length, and optionally a center point.
.avatar {
clip-path: circle(50%);
/* Clips to a circle at the center of the element */
}
/* With a custom center point */
.bubble {
clip-path: circle(40% at 30% 50%);
/* 40% radius, centered at 30% left, 50% top */
}
clip-path: ellipse()
Creates an ellipse clip with separate horizontal and vertical radii.
.oval {
clip-path: ellipse(60% 40% at center);
}
/* rx = horizontal radius, ry = vertical radius */
clip-path: polygon()
Creates any multi-sided shape using a list of x/y coordinate pairs. Each point is a vertex of the shape.
clip-path: polygon(x1 y1, x2 y2, x3 y3, ...);
Triangle
.triangle {
clip-path: polygon(50% 0%, 0% 100%, 100% 100%);
}
DIAGRAM — Triangle polygon:
Point 1: 50% 0% (top center)
Point 2: 0% 100% (bottom left)
Point 3: 100% 100% (bottom right)
▲ ← top center
╱ ╲
╱ ╲
╱_____╲ ← bottom-left to bottom-right
Parallelogram
.parallelogram {
clip-path: polygon(10% 0%, 100% 0%, 90% 100%, 0% 100%);
}
DIAGRAM — Parallelogram:
10%─────────────100%
╱ ╲
0%───────────────────90%
(slanted left and right sides)
Arrow Shape
.arrow {
clip-path: polygon(
0% 20%, 60% 20%, 60% 0%,
100% 50%, 60% 100%, 60% 80%, 0% 80%
);
}
DIAGRAM — Arrow pointing right:
┌──────╮
│ ▶
└──────╯
Pentagon
.pentagon {
clip-path: polygon(50% 0%, 100% 38%, 82% 100%, 18% 100%, 0% 38%);
}
Star
.star {
clip-path: polygon(
50% 0%,
61% 35%,
98% 35%,
68% 57%,
79% 91%,
50% 70%,
21% 91%,
32% 57%,
2% 35%,
39% 35%
);
}
clip-path: inset()
Clips to a rectangle with optional rounded corners. All four sides inset from the element's edges.
/* inset(top right bottom left) */
.cropped {
clip-path: inset(10px 20px 10px 20px);
}
/* With rounded corners */
.rounded-crop {
clip-path: inset(10% round 20px);
}
DIAGRAM — inset(20px):
Before: After inset(20px):
┌──────────┐ ┌────────┐
│ │ │ (20px │
│ content │ → │ gap │
│ │ │ all │
└──────────┘ └sides───┘
clip-path: path()
Uses SVG path syntax for completely custom shapes — curves, bezier arcs, complex outlines.
.custom {
clip-path: path("M 0 50 Q 50 0 100 50 Q 50 100 0 50");
/* A diamond-like curved shape */
}
Animating clip-path
You can animate clip-path between two shapes as long as they have the same number of points. The browser interpolates each vertex.
.btn {
clip-path: polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%);
transition: clip-path 0.4s ease;
}
.btn:hover {
clip-path: polygon(10% 0%, 100% 0%, 90% 100%, 0% 100%);
/* Rectangle morphs to a parallelogram on hover */
}
DIAGRAM — Animated clip-path on hover:
Normal: ┌──────────┐
└──────────┘
On hover: ╱──────────╮
╲──────────╯
(parallelogram — same 4 points, different positions)
Reveal Animation with clip-path
A common technique to reveal elements as they enter the screen:
@keyframes revealFromLeft {
from {
clip-path: inset(0 100% 0 0); /* fully hidden (right side closed) */
}
to {
clip-path: inset(0 0% 0 0); /* fully visible */
}
}
.reveal {
animation: revealFromLeft 0.6s ease-out forwards;
}
clip-path vs overflow: hidden vs border-radius
DIAGRAM — Three ways to clip corners:
border-radius: 50%; → circle, but limited to ellipses
overflow: hidden; → clips to the rectangular box, no shape control
clip-path: polygon(...) → any shape — triangles, hexagons, stars, custom
Common Clip Path Shapes
| Shape | clip-path value |
|---|---|
| Circle | circle(50%) |
| Oval | ellipse(70% 50%) |
| Triangle (up) | polygon(50% 0%, 0% 100%, 100% 100%) |
| Chevron right | polygon(0 0, 75% 0, 100% 50%, 75% 100%, 0 100%, 25% 50%) |
| Rhombus | polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%) |
| Slanted bottom | polygon(0 0, 100% 0, 100% 80%, 0 100%) |
Browser Support Note
All modern browsers support clip-path with circle(), ellipse(), polygon(), and inset(). The path() value has broader support in recent browsers. Add -webkit-clip-path for older Safari support.
.shape {
-webkit-clip-path: polygon(50% 0%, 0% 100%, 100% 100%);
clip-path: polygon(50% 0%, 0% 100%, 100% 100%);
}
clip-path unlocks shapes that are impossible with borders alone. Use it for stylized hero sections, unique image frames, diagonal section dividers, and hover reveal effects — all with pure CSS.
