Build a clip-path from polygons, circles, ellipses and rounded insets, with the fill rule exposed and the value checked before it is shown
Initializing in your browser…
Round corners in px or percent, circular or elliptical, and see the radius the browser will actually paint after the CSS overlap rule scales it down
Generate fake data that is the thing it is labelled: card numbers with a real Luhn check digit, IBANs that pass ISO 7064 MOD 97-10, UUID v4 and v7 per RFC 9562, reserved e-mail and IP ranges, a seed so the same data comes back, and JSON, NDJSON, CSV or SQL output
Build a CSS keyframe animation with the timing function held to what the specification allows: named, cubic-bezier and steps easings, a preview built from the same declarations as the copied CSS, and every problem the browser would refuse named before you paste it
Every shape the tool offers, rendered in a real browser and probed with document.elementFromPoint at eleven points, against what the tool itself says those points should be.
Probed
16 shapes x 11 points, comparing the painted pixels with the tool's own geometry
Browser against tool (Y = painted, n = not)
Triangle browser YnnYnnnY tool YnnYnnnY Pentagon browser YnnnnYnnnYY tool YnnnnYnnnYY Hexagon browser YnnnnYYnnYY tool YnnnnYYnnYY Star browser Ynnnnnnnn tool Ynnnnnnnn Arrow browser YnnnnnnYYnY tool YnnnnnnYYnY Rhombus browser YnnnnYYYY tool YnnnnYYYY ...all 16 shapes agree at every point The pentagram, where the fill rule decides the answer: polygon(nonzero, ...) centre painted polygon(evenodd, ...) centre NOT painted Points sitting exactly on an edge are excluded: there the browser is making a device-pixel rounding decision, not a statement about the shape.
A clip path is a claim about which pixels are painted, so that is what it is checked against rather than the text of the value. Two things had to be fixed before the check could pass at all: the first paint wrote polygon() with no vertices, which is invalid and leaves the element unclipped, and the fill rule was never exposed even though it decides the answer for any shape whose edges cross. Circle, ellipse and inset are now real CSS shape functions rather than polygons approximating curves, so they stay smooth at any size.
Build a clip path from polygons, circles, ellipses or rounded insets, drag the points, and copy CSS that has been checked before you see it. Every shape here was rendered in a browser and probed pixel by pixel against what the tool says it should cover.
Every other CSS generator makes a claim you can argue with. A clip path makes one you can settle: these pixels are painted and those are not. So that is what this tool is checked against. Every shape it offers is rendered in a real browser and probed with `document.elementFromPoint` at eleven points, and the answer is compared with what the tool itself believes about the same points. All sixteen shapes agree at every point that is not sitting exactly on an edge.
The first thing that had to be fixed was more basic. `polygon()` with no vertices is not a valid value: the browser drops the declaration and paints the element unclipped. The previous version filled its point list from an effect that runs after the first render, so its very first paint wrote exactly that, and the generated CSS said `clip-path: polygon();` until the effect landed. The shape is now derived from the preset rather than copied into state, so there is no moment when it is empty.
The second is that a clip path is not only polygons. CSS Masking 1 takes four basic shapes, and `circle()`, `ellipse()` and `inset()` are real functions that scale with the element rather than polygons approximating a curve with straight lines. All four are here. A `circle()` is worth understanding: its percentage radius resolves against the reference box SIZE, which CSS Shapes 1 defines as the square root of half the sum of the squared width and height, not against the width and not against the height. On a 200 by 100 box a 50 percent circle therefore does not reach the left edge.
The third is the fill rule. `polygon()` takes an optional `nonzero` or `evenodd`, and for a shape whose edges cross each other the two give different results: draw a five pointed star as a single self-crossing path and `nonzero` fills the middle while `evenodd` leaves a pentagonal hole in it. The Pentagram preset is there to show it, the control is exposed, and both were verified against what the browser actually paints at the centre point.
Smaller things that were wrong and are not now: the inset slider used `parseInt(x) || 0`, so it worked, but Reset went back to the un-inset shape while the slider still read whatever it was set to; the CSS rounded its coordinates to one decimal place while the preview and the point list used the full float, so the three disagreed by up to half a hundredth of a percent; and the dashed outline over the preview was written with percentages in an SVG `points` attribute, which is not a number there, so the attribute was rejected wholesale and the outline was never drawn at all while the console filled with errors.
Pick Pentagram and switch between nonzero and evenodd. The centre of the star fills and empties, which is the whole difference between the two rules.
Pick Circle. The value is `circle(50% at 50% 50%)`, which stays perfectly smooth at any size, where a polygon approximating it would show its facets when scaled up.
A polygon with one slanted edge cuts a diagonal across a full width section without an image or an extra element.
Hexagons and circles clip a photo to a shape without needing the image itself to be cut.
The Arrow and Chevron presets are the shapes a progress breadcrumb is usually built from.
inset() with a round value gives a rounded rectangle window, which is a clip rather than a border radius and so also clips overflowing children.
An invalid clip-path value is dropped by the browser and the element paints unclipped, with no error anywhere. The most common cause is a polygon with fewer than three points. This tool refuses to write a value that will not parse and says what is wrong instead.
It decides what happens where a shape's edges cross. Draw a five pointed star as one self-crossing path: nonzero fills the middle, evenodd leaves a pentagonal hole. For a shape whose edges never cross, the two rules give the same result.
A polygon is straight lines between points, so it shows its facets when the element is large. circle() is a real curve at any size. Its percentage radius also resolves against the reference box size, the square root of half the sum of the squared width and height, so on a wide box a 50 percent circle does not reach the left and right edges.
It does not change layout: the element still occupies its full box. It does affect hit testing, so the clipped-away parts stop receiving pointer events, which is usually what you want.
For older Safari, yes, and it is emitted first so the standard property wins wherever both are understood. Every current browser understands the unprefixed form.
This runs as client-side JavaScript. Keys, tokens, payloads, and other inputs never leave your device.