border-radius

Avatar of Sara Cope
Sara Cope on (Updated on )

DigitalOcean joining forces with CSS-Tricks! Special welcome offer: get $200 of free credit.

You can give any element “rounded corners” by applying a border-radius through CSS. You’ll only notice if there is a color change involved. For instance, if the element has a background-color or border that is different than the element it’s above.

.element {
  border-radius: 10px;
}
 
 

Constituent properties

border-radius is what we call a “shorthand” property. That means it sets the following individual properties in a single declaration:

  • border-top-left-radius
  • border-top-right-radius
  • border-bottom-right-radius
  • border-bottom-left-radius

Logical properties

Those are referred to as “physical” properties because they set the radius according to the physical location of the corner (e.g. top-left). But border-radius is part of the Logical Properies and Values specification, meaning it has logical equivalents of the physical properties:

Physical propertyLogical property
border-top-left-radiusborder-start-start-radius
border-top-right-radiusborder-start-end-radius
border-bottom-left-radiusborder-end-start-radius
border-bottom-right-radiusborder-end-end-radius

It’s a bit mind-bendy at first, but the order really matters, especially when working with border-radius as a shorthand. The order goes like this, where the first direction refers to the block direction and the second direction refers to the inline direction.

Physical propertyLogical property
top-leftstart-start
top-rightstart-end
bottom-leftend-start
bottom-rightend-end

Syntax

border-radius: <length-percentage [0,∞]>{1,4} [ / <length-percentage [0,∞]>{1,4} ]?
  • Initial value: 0
  • Applies to: all elements
  • Inherited: no
  • Computed values: pair of computed <length-percentage> values
  • Animation: by computed value

The border-radius property takes between one and four length or percentage values, where one value sets the radius for all four corners at once, while four sets each individual corner.

/* Single value */
/* Sets all four corners */
border-radius: 10px;

/* Two values /*
/* top-left and bottom-right top-right and bottom-left  */
border-radius: 25% 0;

/* Three values */
/* top-left top-right/bottom-left bottom-right */
border-radius: 1rem 1.5rem 1.25rem;

/* Four values */
/* top-left top-right bottom-right bottom-left */
border-radius: 8px 10px 12px 14px;

/* Global values */
border-radius: inherit;
border-radius: initial;
border-radius: revert;
border-radius: revert-layer;
border-radius: unset;

So, if we wanted to set a different radius on the top-left and bottom-right but apply the same radius on the top-right and bottom-left together, we can use the three-value syntax:

.element {
  /* top-left top-right/bottom-left bottom-right */
  border-radius: 5px 20px 5px;
  background: #BADA55;
}
 
 

Elliptical rounding (/)

You may also specify the radiuses in which the corner is rounded by. In other words, the rounding doesn’t have to be perfectly circular, it can be elliptical. This is done using a slash (/) between two values:

.element {
  border-radius: 10px / 30px; /* horizontal radius / vertical radius */
}
 
 

Note: Firefox only supported elliptical borders in 3.5+. Older WebKit browsers (e.g. Safari 4 and below) incorrectly treat 40px 10px the same as 40px / 10px.

Values

The border-radius property can accept any valid CSS length unit. That means everything from px, rem, em, ch, vh, vw, and a whole bunch more are fair play.

You may specify the value of border-radius in percentages. This is particularly useful for creating a circle or ellipse shape, but can be used any time you want the border-radius to be directly correlated with the element’s width.

.element {
  border-radius: 50%;
  width: 200px;
}
 
 

Note: In Safari percentage values for border-radius only supported in 5.1+. In Opera, only supported in 11.5+.

Gotchas

There are a few things to watch for when working with the border-radius property:

Clipped background images

If the element has an image background, it will be clipped at the rounded corner naturally:

.element {
  border-radius: 20px;
  background: url(bglines.png); /* will get clipped */
}

Background color bleed

Sometimes you can see a background-color “leak” outside of a border when border-radius is present (here’s a perfect example). To prevent this you use the CSS background-clip property:

.element {
  border-radius: 10px;

  /* Prevent background color leak outs */
  -webkit-background-clip: padding-box; 
  -moz-background-clip:    padding; 
  background-clip:         padding-box;
}

Overlapping border radii

Jay Sitter covered what happens when the value of one corner radius is so big that it overlaps the radius of another corner. Like this example, where we’re going for a “pill” shape on the right side with less rounding on the left:

We’re swtting a radius of 40px on the top-left and bottom-left corners, so why are they so boxy? That’s because the 999em value of the other two corners is covering them up. Jay digs deep into the math behind this and how to prevent it from happening, so it’s worth reading his article for more context.

Demo

Browser support

This browser support data is from Caniuse, which has more detail. A number indicates that browser supports the feature at that version and up.

Desktop

ChromeFirefoxIEEdgeSafari
4*3*9123.1*

Mobile / Tablet

Android ChromeAndroid FirefoxAndroidiOS Safari
1051042.1*3.2*

It’s unnecessary now, but for the absolute best possible browser support, you could prefix the property with -webkit- and -moz- to ensure legacy browsers can join the fun:

.element {
  /* Safari 3-4, iOS 1-3.2, Android 1.6- */
  -webkit-border-radius: 12px; 

  /* Firefox 1-3.6 */
  -moz-border-radius: 12px; 
  
  /* Opera 10.5, IE 9, Safari 5, Chrome, Firefox 4, iOS 4, Android 2.1+ */
  border-radius: 12px; 
}

Notice the order of those properties: the vendor prefixes are listed first and the non-prefixed “spec” version is listed last. This is the correct way to do it. Border radius is a particularly good example of why we do it that way. In slightly more complicated version of using border-radius (where you pass two values instead of one), the older -webkit- vendor prefix would do something entirely different than the “spec” version. So, if we blindly copy-and-paste the same values to all three properties, we could see different results cross-browser. For the most consistency long-term, it’s best to list the “spec” version last.

It’s pretty realistic these days to drop prefixes and just use vanilla border-radius, as discussed here.

Here’s each individual property, with vendor prefixes:

.element {
  -webkit-border-top-left-radius: 1px;
  -webkit-border-top-right-radius: 2px;
  -webkit-border-bottom-right-radius: 3px;
  -webkit-border-bottom-left-radius: 4px;

  -moz-border-radius-topleft: 1px;
  -moz-border-radius-topright: 2px;
  -moz-border-radius-bottomright: 3px;
  -moz-border-radius-bottomleft: 4px;

  border-top-left-radius: 1px;
  border-top-right-radius: 2px;
  border-bottom-right-radius: 3px;
  border-bottom-left-radius: 4px;
}

Each of these values can have a space-separated value as well, like 5px 10px, which behaves the same as a slash-separated value in shorthand (<horizontal-radius> [space] <vertical-radius>).