Skip to content
HexSlate

CSS Clip Path Generator

CSS
.shape {
  clip-path: polygon(100% 50%, 75% 93.3%, 25% 93.3%, 0% 50%, 25% 6.7%, 75% 6.7%);
}
Tailwind v4
[clip-path:polygon(100%_50%,_75%_93.3%,_25%_93.3%,_0%_50%,_25%_6.7%,_75%_6.7%)]
6 points%67 characters of CSS

Percentages, not pixels

A polygon written in percent is resolution-independent: the shape holds when the element is 200px wide and when it is 900px wide, which on a responsive layout is the difference between a shape and a bug. The same polygon in pixels stops being that shape the moment the layout moves. Pixels stay available here because a fixed 24px notch is a real requirement, but they are the exception and the tool says so when you switch.

Percentages are resolved against the reference box, horizontally for x and vertically for y, which means a shape on a wide element is stretched compared to the same shape on a square one. That is usually what you want for a banner and never what you want for an icon. For an icon, make the element square.

Points outside the box are allowed

A vertex at -20% 130% is legal, and it is how an edge is made to run off the element instead of meeting a corner exactly. Nothing here clamps a coordinate for that reason. The handles cannot be dragged outside the pad, so the X and Y boxes in the sidebar are where you type those, which is also why they exist alongside a drag editor.

The four functions are not interchangeable

polygon() takes any number of vertices and is the general case. circle() and ellipse() are curves a polygon can only approximate, and they animate smoothly where a polygon does not. inset() is a rectangle with optional rounded corners, and it is the one to reach for when you are cutting a margin rather than making a shape: it collapses like margin does, and its round keyword takes a full border-radius value.

One rule governs animating between shapes: two polygon() values interpolate only if they have the same number of vertices, in the same order. A five-point shape does not tween into a six-point one; it jumps. The usual workaround is to give the simpler shape a duplicated vertex so both sides have the same count.

Common problems

  • The shape has jagged edges.clip-path is not always anti-aliased, particularly on shallow diagonals in some browsers. A filter: drop-shadow(0 0 0 transparent) or a transform that promotes the element to its own layer usually smooths it, at the cost of a paint layer.
  • Clicks still land on the clipped-away corners. They do not, actually: clip-path clips hit testing too. If you are still getting clicks there, the target is a parent element, not the clipped one.
  • The box shadow disappeared. It is being clipped, like everything else outside the shape. Put the shadow on a parent using filter: drop-shadow(), which follows the clipped outline rather than the box.
  • Text inside gets cut off. Clipping does not reflow content. Add padding, or use shape-outside with the same value so the text wraps to the shape instead of running under it.

Frequently asked questions

Can I use this without a mouse?

Yes. Every vertex is a real button: tab to one, move it with the arrow keys, hold shift for a larger step. The sidebar shows the selected point's coordinates as numbers and takes typed values, including ones outside the element.

What is the reference box?

The border box by default. clip-path accepts a box keyword before the shape, so clip-path: padding-box circle(50%) measures against the padding box instead. It matters the moment the element has a border, and it is one of the least-known parts of the property.

Does it work on images and videos?

On any element, including <img>, <video> and an entire container with content inside it. The clip applies to the element's rendering as a whole, so children are clipped along with the background.

What about shapes a polygon cannot draw?

clip-path also takes path() with an SVG path string, which gives you curves and holes. It is not interpolatable against a polygon and cannot use percentages, so it is a different tool for a different job: hand-draw it in a vector editor and paste the d attribute.