Like basic shapes such as circle(), ellipse(), and polygon(), shape() is used with the clip-path property — but it targets complex drawings rather than simple geometric ones. The function has picked up support in both Chromium and WebKit.
It doesn't open new drawing territory so much as a new way to write it. The path() function already accepts SVG commands directly, as in the example pulled from WebKit's blog post:
<svg viewBox="0 0 150 100" xmlns="http://www.w3.org/2000/svg">
<path fill="black" d="M0 0 L 100 0 L 150 50 L 100 100 L 0 100 Q 50 50 0 0 z " />
</svg>
The coordinates in a <path> can be pasted straight into a CSS path() when clipping an element:
.clipped {
clip-path: path("M0 0 L 100 0 L 150 50 L 100 100 L 0 100 Q 50 50 0 0 z");
}
That syntax is legible only to people who have studied SVG by hand — a niche skill, and one most front-end developers avoid. A more common workflow is drawing in Figma, exporting, and copy-pasting the resulting paths.
The shape() command set
shape() reads like CSS instead of vector data. It uses plain English and native CSS units for lines, arcs, and curves, which also means calc()-ulations can appear inside the drawing.
Setting the origin
Drawing begins with an instruction on where to start. A directional keyword such as from top left anchors the origin at the top-left corner of the element; CSS units work too, so from 0 0 is equally valid. With the starting point established, the commands below take over for lines, arcs, and curves.
A table of the commands:
| Command | What it means | Usage | Examples |
|---|---|---|---|
line | A line that is drawn using a coordinate pair | The by keyword sets a coordinate pair used to determine the length of the line. | line by -2px 3px |
vline | Vertical line | The to keyword indicates where the line should end, based on the current starting point.The by keyword sets a coordinate pair used to determine the length of the line. | vline to 50px |
hline | Horizontal line | The to keyword indicates where the line should end, based on the current starting point.The by keyword sets a coordinate pair used to determine the length of the line. | hline to 95% |
arc | An arc (oh, really?!). An elliptical one, that is, sort of like the rounded edges of a heart shape. | The to keyword indicates where the arc should end.The with keyword sets a pair of coordinates that tells the arc how far right and down the arc should slope.The of keyword specifies the size of the ellipse that the arc is taken from. The first value provides the horizontal radius of the ellipse, and the second provides the vertical radius. I’m a little unclear on this one, even after playing with it. | arc to 10% 50% of 1% |
curve | A curved line | The to keyword indicates where the curved line should end.The with keyword sets “control points” that affect the shape of the curve, making it deep or shallow. | curve to 0% 100% with 50% 0% |
smooth | Adds a smooth Bézier curve command to the list of path data commands | The to keyword indicates where the curve should end.The by keyword sets a coordinate pair used to determine the length of the curve.The with keyword specifies control points for the curve. | smooth by 50% 50% with 50% 5% |
The spec covers considerably more nuance than the table captures.
Interaction limits
shape() can be swapped on hover and focus states like any other clipped value. What the current implementation does not allow is a transition or animation between shapes.



