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: 20pxOuter − 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 = 10pxRadius 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.