One border-radius system

One radius scale; nested corners use outer radius minus padding.

From refactoring-ui, references/advanced-patterns.md “Border Radius System”.

Nested corners

Drag both sliders and watch the corner gap.

Same radius insideBad
Studio deskOak, 160 × 80 cm
inner: 20px
Outer − paddingGood
Studio deskOak, 160 × 80 cm
inner: 12px
.card {
  --radius: 20px;
  --pad: 8px;
  border-radius: var(--radius);
  padding: var(--pad);
}
.card > .media,
.card > .btn { border-radius: max(0px, calc(var(--radius) - var(--pad))); }

One scale, not ten values

Reroll the left; switch the right to Sharp or Soft.

Mixed radiiBad
Acme LtdInvoice #1042 Paid
One systemGood
Acme LtdInvoice #1042 Paid
.soft  { --radius-sm: 4px; --radius-md: 8px; --radius-lg: 12px; }
.sharp { --radius-sm: 2px; --radius-md: 4px; --radius-lg: 6px; }
.badge  { border-radius: var(--radius-sm); }
.input,
.button { border-radius: var(--radius-md); }
.card   { border-radius: var(--radius-lg); }
.avatar { border-radius: 9999px; }

Small things, small radius

Find one radius that suits every element.

One radius for allBad
Rename projectDraft
badge = button = dialog = 10px
Radius grows with sizeGood
Rename projectDraft
badge 4 · button 8 · dialog 16
.badge  { border-radius: var(--radius-sm); }
.button { border-radius: var(--radius-md); }
.dialog { border-radius: var(--radius-xl); }

Why it matters, pros and cons

Why it matters

Radius sets personality, and mixed values send mixed signals. Nested corners stay concentric only when inner equals outer minus padding.

Pros

  • Four tokens cover every component.
  • Padding looks even at the corners.
  • Sharp to soft is one token change.

Cons

  • Padding above radius squares the inner corner.
  • Pills and avatars sit outside the scale.
  • Third-party widgets bring their own radii.