How to nest rounded corners

Sep 18, 2026 · Interface · 3 min read

Put a rounded image inside a rounded card, give both the same radius, and something feels off. Most people cannot say what, but they notice. The corners look pinched, the frame looks thicker at the corners than along the edges, and the whole component reads as slightly cheap.

The cause is geometry. A rounded corner is a quarter circle. When two quarter circles with the same radius sit inside each other, their centers are in different places, so the gap between the curves is not constant. It swells at the corner and shrinks along the straight edges. Your eye reads that swelling as a mistake.

The rule

Nested corners should share a center. Then the gap between the two curves stays the same all the way around, exactly like the straight edges.

inner radius = outer radius - padding

If the card has a 22px radius and 6px of padding, the image inside gets 16px. That is the exact setup on the gallery cards of this site.

Not recommended
Recommended
Left: the same radius on both. Right: the outer radius minus the padding. Turn on Show values to see the numbers.

Writing it in CSS

Hard-coding the inner value works until someone changes the padding. Tie the two together with custom properties so they can never drift apart.

.card {
  --radius: 22px;
  --pad: 6px;
  padding: var(--pad);
  border-radius: var(--radius);
}

.card > .media {
  /* Never below zero, even when the padding is larger than the radius. */
  border-radius: max(0px, calc(var(--radius) - var(--pad)));
}

The max() matters. Once the padding is as large as the outer radius, the inner corner should simply be square. A negative radius is ignored by the browser, which quietly falls back to the old value and brings the bug back.

Borders count as distance too

If the outer element has a border, the space between the curves is the padding plus the border width. Subtract both:

inner radius = outer radius - border width - padding

Shadows and outlines do not count. They are drawn outside the box and do not move the inner edge.

Pills solve themselves

A pill is an element whose radius is half its height. Inside a pill, a smaller pill with the same padding on every side is automatically concentric: its height is the outer height minus twice the padding, so half of it is exactly the outer radius minus the padding. This is why border-radius: 999px on both a segmented control and its sliding thumb always looks right.

Three levels deep

The rule chains. A dialog at 24px, a panel inside it with 8px of padding at 16px, and a button inside that with 6px of padding at 10px. Every step subtracts its own padding. If a level gets so small that the radius drops below about 4px, switch to square corners on purpose instead of letting a 1px curve look like an accident.

Checklist

  • Inner radius equals outer radius minus padding (and minus the border, if any).
  • The subtraction is wrapped in max(0px, ...).
  • Radius and padding live in shared tokens or custom properties, not separate magic numbers.
  • Pills inside pills use a full radius on both.
  • Very small inner radii are replaced with square corners on purpose.

This piece expands on the Interface rules in my cheat sheet, where every rule has a live example.

Keep readingWhy centered icons look off-centerOptical alignment, icon stroke weight and uneven padding: three places where correct numbers produce wrong-looking UI.