CSS corner-shape: bevels and scoops without clip-path

Anything beyond a plain rounded corner has meant reaching for clip-path, an SVG mask, or a pile of radial-gradient tricks. They work, they cost you rendering performance, and they are miserable to maintain a year later. Chromium browsers now ship the corner-shape property, which does the same job natively.

I have been writing CSS for more than 14 years, back to when a rounded corner took five background images. border-radius ended that era, but it only ever gave us one curve. Ask for beveled edges on a gaming panel or a scooped ticket stub and you were straight back into fragile workarounds. The real problem with clip-path is that it ignores borders and box shadows, so you stack pseudo-elements just to get a stroke around the shape. corner-shape changes the geometry of the box itself, so none of that is necessary.

How the corner-shape property works with border-radius

corner-shape does not replace border-radius, it works alongside it. border-radius sets the size of the corner area, and corner-shape sets its shape. With no radius there is nothing for the shape to act on, so declare both or nothing changes.

The spec has a handful of values, and between them they cover most of what custom UI actually asks for:

  • round is the default we have all been using.
  • squircle is the smooth superellipse curve Apple uses, which suits app icons.
  • bevel cuts a straight diagonal between the radius points.
  • scoop curves inward instead of outward, the classic editorial look.
  • notch makes a sharp inward cut and reads as mechanical or stamped.

If you already lean on Tailwind or utility classes, this takes a chunk of per-component CSS off your hands.

The old way: a clip-path hack

This is what most of us shipped for years. It looks fine until you add a border or a shadow and watch the clip cut straight through it.

/* The brittle way: Borders won't follow this! */
.ticket-hack {
  clip-path: polygon(0% 15%, 15% 0%, 85% 0%, 100% 15%, 100% 85%, 85% 100%, 15% 100%, 0% 85%);
  background: #f0f0f0;
  /* border: 2px solid red; <-- This will be partially invisible */
}

The native version

Here the border and the shadow follow the outline, because the browser knows where the edge of the element actually is.

/* The native way */
.ticket-modern {
  border-radius: 20px;
  corner-shape: scoop;
  border: 2px solid var(--primary);
  box-shadow: 0 10px 20px rgba(0,0,0,0.1);
}

Shipping it as progressive enhancement

Support today is Chrome 139 and up, plus the other Chromium browsers. Firefox and Safari fall back to ordinary rounded corners, which is fine. That is the whole case for progressive enhancement: a rounded corner is a perfectly good baseline, and the browsers that can do more get more. Partial support is not a reason to sit on the feature.

Pair it with modern CSS layout logic and keep the upgrade inside an @supports block.

@layer demo {
  @supports (corner-shape: bevel) {
    .product-badge {
      border-radius: 0 16px 16px 0;
      /* Only enhance the corners that support it */
      corner-shape: round bevel bevel round;
      padding-inline: 1.5rem;
    }
    
    .card {
      border-radius: 40px;
      corner-shape: squircle;
    }
  }
}

squircle on a card is the kind of change nobody notices and every designer likes. A circular arc meeting a straight edge leaves a small visible kink; the superellipse smooths it away. It is the iOS look, and most people cannot tell you why it feels better.

Why developers should ship this now

Dropping the SVG masks and the clip-path blocks takes real weight out of a stylesheet, and it gives the browser less work at paint time. You also get animation for free: superellipse() interpolates, which the old hacks never really managed.

If this kind of CSS work is eating your dev hours, I take it on as client work. I have been doing WordPress and front-end architecture since the 4.x days.

Where this leaves border-radius

corner-shape is the piece border-radius has been missing all along. It still feels experimental, and outside Chromium it does nothing at all, which is exactly why it belongs behind @supports rather than in your baseline. The spec text is in the W3C CSS Borders Module, and the CSS-Tricks Almanac has the shorter version.

author avatar
Ahmad Wael
I'm a WordPress and WooCommerce developer with 15+ years of experience building custom e-commerce solutions and plugins. I specialize in PHP development, following WordPress coding standards to deliver clean, maintainable code. Currently, I'm exploring AI and e-commerce by building multi-agent systems and SaaS products that integrate technologies like Google Gemini API with WordPress platforms, approaching every project with a commitment to performance, security, and exceptional user experience.