Border-radius often gets treated as an afterthought: a value typed into CSS per component, usually copied from whatever the last component used. That's how interfaces end up with five slightly different corner roundings and no one able to say why. Radius deserves the same systematic treatment as color or spacing, since it does more communicative work than it gets credit for.
Quick answer: border radius sizes
These are sensible defaults for a standard web UI, not laws, but they're a reliable starting point:
| Element | Radius | Token |
|---|---|---|
| Tags, checkboxes, compact buttons | 4px | sm |
| Buttons, text inputs, small cards | 8px | md |
| Cards, modals, panels | 16px | lg |
| Pills, avatars, toggle switches | 9999px | full |
| Tables, dashboards, data-dense UI | 0–4px | sm or none |
| Anything inside a rounded parent | outer − padding | see the nested rule |
Want to see these values on real components? Build and preview a scale in the Radius Builder.
Border-radius is a personality decision, not a detail
Sharp, square corners read as precise, technical, serious: think financial dashboards, developer tools, dense data interfaces. Rounded corners read as approachable and soft: think consumer apps, wellness products, anything trying to feel less intimidating. Neither is correct on its own. The mistake is picking a radius without deciding which impression the product actually wants.
It's also why copying a competitor's radius value rarely works well. It was chosen for their product's personality, not yours.
Build a scale, not one-off values
The same problem that affects font sizes affects radius. Pick values one component at a time and inconsistency follows for free. A small set of radius tokens solves it. In CSS, that's four custom properties defined once and referenced everywhere else:
--radius-sm: 4px;--radius-md: 8px;--radius-lg: 16px;--radius-full: 9999px;
Every component then uses border-radius: var(--radius-md) rather than a hard-coded number.
Four tokens, referenced everywhere, instead of a scattered set of pixel values with no shared logic. When the product's rounding personality changes, it's a token edit, not a find-and-replace across every component file.
If you're on an 8px spacing grid, keeping radius on the same rhythm (4 / 8 / 16) makes the whole system feel more deliberate, since the curves echo the spacing steps.
Match radius to component size
The most common radius mistake is applying the same pixel value to everything regardless of how big the element is. An 8px radius reads as a meaningful curve on a 32px button, but on a 400px-wide card the same 8px looks barely rounded at all. As a rule, radius should scale roughly with the element: larger surfaces need a larger radius to look as soft as a small element with a small radius.
The before/after is easy to see. Give every element the same flat 6px and the interface looks undecided: the small tag is a little too round, the card not round enough. Switch to the scale, 4px on the tag, 8px on the input and button, 16px on the card, and each element gets the right amount of rounding for its size. Nothing else changed; only the relationship between radius and size did.
Concretely: picture a 40px-tall button sitting on a 480px-wide pricing card. At a flat 6px, the card's corners look accidental, as if rounding was applied and then forgotten. Move the button to 8px and the card to 16px and the hierarchy snaps into place: the small control reads as crisp and clickable, the large surface as a soft, contained panel.
Nested radius: inner vs. outer corners
When one rounded element sits inside another, a card with padding wrapping a rounded image, or a button inside a rounded input group, using the same radius on both looks subtly wrong. The gap between the two shapes gets wider at the corners, so the inner element seems to bulge.
The fix is a simple rule: inner radius = outer radius − padding. If a card has a 16px radius and 8px of padding, the element hugging its inside corner should use an 8px radius (16 − 8). The two curves then run parallel instead of fighting each other. When the result would be zero or negative, the inner element should just have square corners, which is correct: there isn't enough room left for a curve to read.
This comes up more often than it seems. A rounded avatar inside a rounded card, an image filling the top of a panel, a highlighted row inside a rounded table, a selected item inside a rounded menu: all of these are nested corners. Design tools that expose radius and padding as tokens make the subtraction almost automatic, because both values are already named and sitting right next to each other.
Full/pill radius vs. contained radius
These solve different problems and shouldn't be used interchangeably:
- Full/pill radius (avatars, badges, toggle/switch controls, some buttons): the corner radius is at least half the element's height, producing a capsule or a perfect circle. Reserve it for small, discrete controls.
- Contained radius (cards, inputs, modals, larger buttons): a partial curve that softens the shape without fully rounding it off. This is where the sm/md/lg tokens do their work.
Common border-radius mistakes
Most radius problems come down to a handful of recurring errors:
- Too many values. Five or six one-off radii with no shared logic, the exact inconsistency a token scale exists to prevent.
- The same px everywhere. One flat value applied regardless of size, so small controls look too round and large surfaces look barely touched.
- Pill radius on large surfaces. A full radius on a wide card or panel turns it into a capsule and loses the crisp edge the layout needed.
- Ignoring nested radius. Matching inner and outer corners instead of subtracting the padding, so the inner shape bulges.
- Radius / shadow mismatch. A heavily rounded card paired with a hard-edged shadow, two surface cues that disagree about how soft the element is.
Radius doesn't work alone
Rounding and shadow are really one concern: how a surface visually separates from the background. They read together, not independently. A heavily rounded card with a hard-edged shadow looks unfinished; the two need to be designed as a pair. Our companion piece on shadow and elevation systems covers this, or set both up together in the Design Language Studio, where radius and shadow are handled as a single surface-treatment step.
To build and preview a radius scale on its own, use the Radius Builder.
To see how one radius scale holds up across a whole page — from pill buttons in a hero section to the plan cards in a pricing section — preview it in Section Studio, where every layout renders in your own tokens.
Border radius FAQ
What is a good border radius for buttons?
For a standard button around 40px tall, 8px is the most common default. Compact buttons and tags look better at 4px, and pill-shaped buttons use a full radius (9999px). Whatever you choose, use the same token for every button of that size.
Should I use px or rem for border-radius?
Most design systems use px, because corners usually shouldn't grow when a user increases their text size. rem works too if you want corners to scale with text. The bigger win is defining the value once as a token, so the choice lives in one place.
What does border-radius: 9999px mean?
Any radius of at least half the element's height gives fully rounded ends. 9999px is simply a number big enough to do that for any element, so it reliably makes pills and circles. Using 50% instead turns non-square elements into ovals, which is rarely what you want.
How do I calculate the radius of a nested element?
Subtract the padding from the outer radius: a 16px card with 8px of padding needs an 8px inner radius. If the result is zero or less, give the inner element square corners.