CSS & layout

border-shape is the property clip-path always owed you

border-shape is the property clip-path always owed you

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)

Related
CSS & layout

CSS anchor positioning: two properties do the wiring

Anchor positioning has landed in every major browser engine. Two properties, a keyword grid, and a fallback list replace the JavaScript most floating-UI widgets used to need.

July 7, 2026
CSS & layout

Pseudo-classes are states, not events

CSS-Tricks reframes the everyday choice between :hover, :focus-visible, :has() and the matching JavaScript event listeners. The piece also previews the proposed event-trigger syntax in the Animation Triggers spec, which would let CSS bind animations to events instead of states.

June 29, 2026
CSS & layout

Opposing scroll columns with one view() timeline and three keyframe sets

CSS-Tricks walks through making adjacent columns drift in opposite directions as the page scrolls, with no JavaScript. The trick is a per-item animation-timeline: view() and animation-range: entry 0% cover 100%, repeated across three keyframe sets.

June 25, 2026