border-shape is the property clip-path always owed you
Dex Halloran
Every time you slapped a clip-path on a card and then added a border, you watched the border evaporate. Same with box-shadow. Same with outline. The element got cut into a nice shape, and every piece of decoration you had painted around it got cut off with it. That was fine, because we didn't have a choice. It's not fine anymore.
CSS-Tricks has an explainer by Temani Afif on the incoming border-shape property, and the pitch is the one thing you actually want: shape the box, keep the border. Verdict up front — this is the property clip-path should have shipped with, and I'm honestly relieved it exists.
Why clip-path was never the answer
Here's the mechanism. clip-path (and mask) clip the whole element after painting, decorations included. Your 8px red border? Painted, then clipped along the same path as everything else. The article is uncompromising on this: put a border on a clipped element and, as it says, borders are "a big NO." Same physics for box-shadow, same for outline. Anything living outside the box or riding its edge gets guillotined at the clip.
border-shape swaps the model. It doesn't clip. It shapes. The border, the box-shadow and the outline follow the new outline instead of the rectangle underneath. That is the whole trick, and it is a big one.
Same vocabulary, different job
You already know the syntax. From the article:
.shape {
border-shape: shape() | polygon() | ...;
}
It accepts the same values as clip-path, including the shape() function. So if you can draw a path for a clip, you can draw the same path here, and then paint on it:
.shape {
border: 8px solid red;
border-shape: /* your shape code */;
}
There's a stroke mode (one shape) and a fill mode (two shapes) where the border renders as the area between the two paths. The article shows the fill-mode idea with an inset-plus-circle combo:
.box {
border-shape: inset(0 -100vw) circle(0);
border-color: pink;
}
Two paths, one border, no wrapper div. If you rebuilt that in 2020 with pseudo-elements, overflow: hidden, and a prayer, yeah. Retire the prayer.
The shapes family finally clicks
Here's the rad part. border-shape doesn't stand alone. The shape() function itself is now Baseline according to the article, so you can lean on it in both clip-path and border-shape values with the same SVG-style syntax. And corner-shape, the sibling that rides on border-radius and takes keyword values round, scoop, bevel, notch, and squircle, handles the corner-level story. Corners get corner-shape. Whole outlines get border-shape. Arbitrary geometry lives in shape(). It's the first time CSS shapes feels like a system instead of a pile.
The catch worth flagging
Support is Chromium-only right now, per the article. So this isn't ship-it-Monday material for a public site. It's the try-it-in-a-side-project stage — draw the shapes, poke at fill mode, work out what a graceful non-Chromium fallback looks like. The property has too obvious a purpose to sit in one engine for long, but "obvious" and "ships" are different words in CSS-land.
Kicker
border-shape isn't new syntax to learn. It's clip-path values wired to a job clip-path could never actually do. Nine out of ten. The only reason it isn't a ten is that I want to see it in Gecko and WebKit before I get truly loud about it.
Source: CSS-Tricks (css-tricks.com)