Skip to main content

The Math Behind Nesting Rounded Corners

By Paul Hebert

Published on October 26th, 2022

Topics

I was recently designing an interface with a lot of rounded corners. I wanted to make sure the corners were consistent, so I created a --border-radius custom property and went wild rounding those corners.

But, I quickly ran into a problem. When I nested an element with a rounded corner inside of a rounded container it looked off somehow:

Awkward Rounded Corners One rounded rectangle nested inside another. They both have the same border radius but this leaves an awkward gap between the rectangle’s corners.
When you use the same radius for both elements, the space between elements increase awkwardly in the corners.
Fixed Rounded Corners One rounded rectangle nested inside another. The inner rectangle has a smaller border radius which makes it nest nicely in the larger rectangle.
I’d prefer the corners to nest nicely like this.

This threw me off at first. I was using the same value for both corners. Why didn’t they match up?

A Rounded rectangle with a circle covering its corner

To fix this, I had to take a step back and think through how CSS border-radius actually works. It can be helpful to imagine each corner holding a little circle. What border-radius is actually doing is setting the radius of these tiny circles.

I’m not Cloud Four’s resident circle expert, but thinking about rounded corners as circles helped me understand the math behind nesting rounded corners. To nest one circle inside of another, the inner circle needs a smaller radius than the outer circle.

A quarter of a circle nested inside the quarter of another circle. The inner circle's radius is labeled 30. The outer circle's radius is labeled 50, and the space between the circles is labeled 20.

The difference between the two circles’ radii is the gap between the outer circle and the inner circle. We can apply this same logic to determine the correct value for our rounded corners.

Here’s the equation to determine the inner element’s border-radius:

outerRadius - gap = innerRadius

You can play with the demo below to see how changing the outer border-radius, or the gap impacts the inner border-radius:

See the Pen Nested Radius Calculator by Paul Hebert (@phebert) on CodePen.

This can also be expressed as a CSS calc statement:

--outer-radius: 1em;
--padding: 0.5em;
--inner-radius: calc(var(--outer-radius) - var(--padding));
Code language: CSS (css)

I’m not sure what this means yet when it comes to managing border-radius tokens in design systems. Should we be storing multiple border-radius tokens (inner and outer)? Or does it make more sense to store one primary radius token, and dynamically calculate the rest using calc?

At the moment, I’m leaning towards using calc, but I’m still figuring out the best practices here. In the meantime, understanding this math will help me add a little bit more polish to interfaces with rounded corners.

Comments