CSS Tip: Better Rounded Borders

Explaining Markdown

We’ve all used border-radius in our designs to round the corners of images, divs, navs, etc… But have you ever noticed what happens when a thick border is added to an element with a border radius?

As we learned in my CSS Deep Dive on the subject, the rounded corners in border-radius are formed by the radius of a quarter circle.

The quarter sections of each circle form the rounded corners of the element.

When Thick Borders Connect

There’s a slight issue that occurs when we pair border-radius with a thick border-width. The following image, for example, has a radius value that’s twice the border thickness.

.mike {
  border-radius: 12px;
  border: 6px solid crimson;
}

mike-br-1

No issues just yet.

But, if we make the border-width value larger than border-radius, we lose the rounded corners – the edges in our image become squared.

.mike {
  border-radius: 12px;
  border: 14px solid crimson;
}
mike-br-2

As the border gets wider, the image’s corners become squared.

Why Does This Happen?

This is because border-radius actually shapes the outer part of a border––not the inner. The inner radius shape is determined by the border-radius value minus the border thickness. This results in an inner radius that’s usually smaller than the outer radius.

So if the border-width value is greater than border-radius, we see the effect of a quarter radius connecting two borders that are thicker than the actual radius.

Notice the squared inner radius:

square-inner

To make both radiuses proportional, we’ll need to adjust the radius value to about double the border width, or the sum of border-width and border-radius.

.mike {
  border-radius: 26px;
  border: 14px solid crimson;
}

mike-br-3

When we change the border-radius value to 26px, we get the rounded corners back in our image.

The Box-shadow Method

When we generate a box shadow, the shadow follows the border radius of the element. With that in mind, we can use the optional box-shadow spread value to create what looks exactly like a border.

The spread radius sets the spread distance of the box shadow. If we set the offsets and blur to 0, the spread value defined renders a hard-edged border around the element.

.mike {
  border-radius: 12px;
  box-shadow: 0 0 0 14px crimson;
}

The result looks exactly like our border style example. But now we don’t have to worry about increasing border-radius every time we increase the border width because the spread value will always follow the radius.

mike-br-4

Using Sass Variables

If we’re using a preprocessor like Sass, we can create variables for the border width and radius, then use a simple math operation that proportionality shapes the radius.

$border-width: 14px;
$radius: $border-width*1.9;  

.mike {
  border: $border-width solid crimson;
  border-radius: $radius;
}

Conclusion

The box-shadow method discussed does come with a caveat. Since box shadows are not part of an element’s box model, the faux borders overlap parts of other inline or floated elements, so we’ll need to compensate with extra margins.

CSS box shadows are supported in all the latest browsers, including IE9+.

Guil Hernandez

Guil is the front-end design teacher at Treehouse. You can follow Guil on Twitter at @guilh.

Comments

20 comments on “CSS Tip: Better Rounded Borders

  1. I like that you included a Sass example as well. This is great knowledge. Something I’ve experienced and found workarounds for, but never questioned why it occurred.

  2. While this does work, there are a few extra caveats which were not mentioned; the most glaring of which is size.

    Due to this being a shadow, it is not computed in size and position calculations the way a border is… in fact, shadow really isn’t a part of those calculations at all.

    This can lead to situations where elements are overlapping strangely on the web page, and can be fairly hard to debug.

    A quick fix for this is to go ahead and set a matching border for any element you do this with… this way, the border is calculated, and positions and sizing work correctly. To get rid of the squared internal corner, just set the border’s color to ‘transparent’.