Boise ID
00 00
Do you think it's going to rain today?
Use clip-path instead of border-radius for CSS circles

In building quality interfaces, every pixel must be deliberately painted. As web developers, we have little direct control over the graphics pipeline and the particularities thereof can sometimes result in frustrating problems with rendering.

One such problem is the appearance of shapes and anti-aliasing. Anti-aliasing is a technique to make the edges in graphics appear smooth instead of pixelated and jagged.

border-radius, overflow: hidden, and anti-aliasing

Jagged edges can appear in place of smooth, clean corners when overflow is used in conjunction with border-radius. For some reason, the element which is given rounded corners is anti-aliased but its children, who are being clipped with overflow: hidden;, are not.

Here's an example of a button with a common visual effect where the anti-aliasing problem is clear (interact with it to see the problem):

Menu
button.module.css
.button { background-color: var(--blue-grey); width: 6rem; height: 6rem; border-radius: 9999rem; overflow: hidden; }

The circle is nice and smooth until the red-pink backdrop slides in. Since that backdrop is clipped by the hover property of the button, the edges of the circle become jagged. This will vary between device hardware and browser version, and it's possible that by the time you're reading this the problem has been fixed. As of now, it's very much an issue and professional devs don't ship ugly interfaces.

clip-path to the rescue

clip-path is a powerful CSS property that allows you to create a region that determines which parts of an element should be shown. It's another way to produce circular elements, though border-radius is preferred.

Here's the same button, but this time using clip-path instead of overflow: hidden;:

Menu
button.module.css
.button { background-color: var(--blue-grey); width: 6rem; height: 6rem; clip-path: circle(); }

Let's take a closer look at the results, side-by-side:

Comparison of border-radius and clip-path
border-radius in conjunction with overflow: hidden; (left) and clip-path: circle(); (right)

Much better! The edges are smooth and clean. This is ready to ship.

Another trick!

When passing the circle() function to clip-path, you might not need to specify a size or location. It defaults to a circle centered horizontally matching the full width of the element.

MacCarrithers