Most developers use border-radius with a single value. border-radius: 8px for cards, border-radius: 50% for circles, maybe border-radius: 9999px for pill-shaped buttons. That covers 90% of use cases. But the property accepts up to eight values, and the shapes you can create with the full syntax are surprisingly versatile.
Let me show you what the full specification actually allows.
The shorthand is hiding complexity
The border-radius property is shorthand for four individual properties:
border-top-left-radius: 10px;
border-top-right-radius: 10px;
border-bottom-right-radius: 10px;
border-bottom-left-radius: 10px;
Each of these individual properties accepts two values: a horizontal radius and a vertical radius. When they're different, the corner becomes an elliptical arc instead of a circular one.
/* Circular corner: 10px radius */
border-top-left-radius: 10px;
/* Elliptical corner: 20px wide, 10px tall */
border-top-left-radius: 20px 10px;
The full shorthand uses a slash to separate horizontal and vertical radii:
/* All corners: 20px horizontal, 10px vertical */
border-radius: 20px / 10px;
/* Each corner different, horizontal / vertical */
border-radius: 10px 20px 30px 40px / 5px 10px 15px 20px;
Before that slash, you're setting the horizontal radius for each of the four corners (top-left, top-right, bottom-right, bottom-left, following the standard CSS clockwise order). After the slash, the vertical radii in the same order.
Organic shapes with eight values
The slash syntax is the key to creating shapes that don't look like they were made with a compass and straightedge. By varying horizontal and vertical radii independently across all four corners, you can create organic, blob-like shapes:
/* Organic blob shape */
.blob {
border-radius: 60% 40% 30% 70% / 60% 30% 70% 40%;
width: 200px;
height: 200px;
background: #6C5CE7;
}
This produces a shape that looks like a smooth stone or a melted circle. It's the same technique behind the "blob" shapes that have become popular in modern web design. No SVG needed, no clip-path, just border-radius with asymmetric values.
You can animate these values for a morphing effect:
@keyframes morph {
0% { border-radius: 60% 40% 30% 70% / 60% 30% 70% 40%; }
50% { border-radius: 30% 60% 70% 40% / 50% 60% 30% 60%; }
100% { border-radius: 60% 40% 30% 70% / 60% 30% 70% 40%; }
}
.blob {
animation: morph 8s ease-in-out infinite;
}
This creates a constantly shifting organic shape, which makes for compelling hero section backgrounds or decorative elements.
Percentage vs pixel values
Percentages and pixels behave differently, and mixing them can produce unexpected results.
Pixel values create corners with a fixed radius. A border-radius: 20px corner looks the same regardless of the element's size.
Percentage values are relative to the element's dimensions. border-radius: 50% creates a circle only when the element is square. On a rectangle, it creates an ellipse. border-radius: 50% actually means "the horizontal radius is 50% of the element's width, and the vertical radius is 50% of the element's height."
/* This is a circle (square element) */
.circle {
width: 100px;
height: 100px;
border-radius: 50%;
}
/* This is an ellipse (rectangular element) */
.ellipse {
width: 200px;
height: 100px;
border-radius: 50%;
}
For pill-shaped buttons where the height varies, use a large pixel value rather than 50%:
/* Works regardless of height */
.pill {
border-radius: 9999px;
}
/* 50% would create an ellipse on non-square elements */
The corner overlap rule
What happens when your border-radius values are too large for the element? If two adjacent corners overlap, the browser proportionally reduces all radii until they fit. This is why border-radius: 9999px works for pills -- the browser sees that 9999px is far larger than half the element's dimension and scales it down to the maximum that fits, which is half the shorter side.
This is defined in the spec as "corner curves must not overlap." It means you can be generous with your radius values and the browser will handle the constraint resolution.
Practical patterns
Ticket or coupon shape:
.ticket {
border-radius: 8px;
position: relative;
}
.ticket::before,
.ticket::after {
content: '';
position: absolute;
width: 20px;
height: 20px;
background: white; /* match page background */
border-radius: 50%;
top: 50%;
transform: translateY(-50%);
}
.ticket::before { left: -10px; }
.ticket::after { right: -10px; }
Top-only rounding (tabs, top cards):
.tab {
border-radius: 8px 8px 0 0;
}
Asymmetric card (one side rounded):
.card-left {
border-radius: 12px 0 0 12px;
}
Superellipse approximation:
iOS icons use a superellipse (squircle), not a simple rounded rectangle. CSS border-radius can't perfectly replicate a superellipse, but you can get close:
.squircle {
border-radius: 22%;
/* For a closer match, use clip-path with an SVG path */
}
True squircles require clip-path or an SVG mask, but 22% radius on a square element is a reasonable approximation for most UI work.
Common mistakes
Using
border-radius: 50%for avatar circles without ensuring the image is square. If the source image has a different aspect ratio and you're usingobject-fit: cover, the border-radius still works. But if the container itself isn't square, you get an ellipse.Forgetting that
overflow: hiddenis needed for images.border-radiusclips the element's background and border, but child content (like an<img>tag) overflows by default. Addoverflow: hiddento the container.Inconsistent radius across a design system. Pick a scale and stick to it. Common scales are 2px, 4px, 8px, 12px, 16px, 24px (doubling progression) or 4px, 6px, 8px, 12px, 16px (smaller steps for subtle differences).
Not accounting for borders.
border-radiusapplies to the outer edge of the border. The inner edge's radius isborder-radius - border-width. A 1px border with 4px radius creates a 3px inner radius. If the border is thick and the radius is small, the inside corners can appear sharp even though the outside is rounded.Animation performance. Animating border-radius causes repaints. For smooth animations, prefer transforms and opacity when possible. When you must animate border-radius (like the blob morph above), ensure the element has
will-change: border-radiusand test on lower-end devices.
For visually experimenting with all eight values and seeing the resulting shape in real time, I built a border radius generator at zovo.one/free-tools/border-radius-generator that lets you drag corners independently and copy the CSS.
border-radius is one of those CSS properties where the basic usage is trivial but the full power is hidden behind a syntax most people never explore. Eight values, a slash, and you have an organic shape generator built into every browser.
I'm Michael Lip. I build free developer tools at zovo.one. 350+ tools, all private, all free.
Top comments (0)