clubmate.fi

A good[ish] website

Web development blog, loads of UI and JavaScript topics

CSS beveled corners

Filed under: HTML/CSS— Tagged with: beveled, gradinets, sprite

Beveled corners aren’t as easy to achieve as rounded ones, but there’s few extremely handy methods to do them, other one even works down to IE8.

2013.10.28, see my new article on this including a lot of cool Sass mixins to do all the dirty work.

2013.09.17, added a new technique and better demos.

The a little hacky by still semantic IE8 supporting method

It turns out, we can do trapezoids with CSS. What we'll do is to place a trapezoid shaped :before and :after elements on top and under the box.

The HTML:

<div class="module">Some content here...</div>

And the CSS looks like this (Sass again, or SCSS)

$color-gray: #aaa;

.module {
  background: $color-gray;
  position: relative;
  margin: 30px 0;
  padding: 0 20px;
}

.module:before,
.module:after {
  box-sizing: border-box;
  border-style: solid;
  border-color: transparent;
  border-width: 20px;
  content: '';
  display: block;
  left: 0;
  position: absolute;
  width: 100%;
}

.module:before {
  border-top-width: 0;
  border-bottom-color: $color-gray;
  top: -20px;
}

.module:after {
  border-bottom-width: 0;
  border-top-color: $color-gray;
  bottom: -20px;
}

A demo:

See the Pen HcIog by hilja (@hilja) on CodePen

Plusses on this technique:

  • No unsemantic extra elements
  • No images
  • Can be used against a background photo (a big +)
  • Works on IE8

And the minuses:

  • A bit long a hacky (but only a tiny bit)
  • You can't have border for the whole box. What you can do, is to simulate the border with box-shadow, but then it's not anymore IE 8 compatible.

The CSS3 way with gradients and multiple backgrounds

The 4 backgrounds are positioned with background-position to the corners. Then, corners are cut off with angled (45deg, 135deg, 225deg, 315deg) gradients.

Very simple and nice HTML

<pre data-language="HTML" class="language-markup">`
<div class="box">
  Some content here... (this <p> is not needed here btw)
</div>

And the CSS (add vendor prefixes)

$color-green: #aaa;

.box {
  background: $color-green; /* fallback */
  background: linear-gradient(45deg, transparent 20px, $color-green 20px),
    linear-gradient(135deg, transparent 20px, $color-green 20px),
    linear-gradient(225deg, transparent 20px, $color-green 20px),
    linear-gradient(315deg, transparent 20px, $color-green 20px);
  background-position: bottom left, top left, top right, bottom right;
  background-size: 50% 50%;
  background-repeat: no-repeat;
  padding: 20px;
}

Demo time:

See a Demo LtpcD

Plusses:

  • No unsemantic extra elements
  • No images
  • Can be used against a background photo (a big +)

Minuses:

  • IE8 and 9 not supported

This technique is invented by Lea Verou. See the original article here.

Everything below this point is pretty much irrelevant. Unless you wanna support IE 6 or 7.

The good old browser compliant way with loads of elements and a sprite

There is absolutely nothing new or exiting in this technique, but it works on all browsers, and in the end, is not that heavy or bad. It needs a sprite, but you probably already load a sprite in your theme, right? When saved as png8 with alpha transparency on in Fireworks, it weights 427bytes. If it's a part of a bigger sprite, not even that. The unsemantic empty divs are of course a drag, but imho, we should not stress over semantics too much, right?

How it works is that we put a div in every corned and apply a background image to that, to diagonally cut half of the div. The background image needs to be same color as the background it is against, white in this case.

Plusses

  • Works on all browser
  • Looks great

Minuses

  • Loads of unsemantic empty elements
  • Uses images
  • Can't be used against a background photo

The sprite, against a gray background, that we’ll put into the divs looks something like this:

A sprite image with white triangles

The verbose HTML

<div class="box" id="images">
  Beveled corners with god old sliding doors method with sprites.

  <div id="top-left"></div>
  <div id="top-right"></div>
  <div id="bot-right"></div>
  <div id="bot-left"></div>
</div>

And the CSS

#images {
  background: Pink;
}
#images div {
  background: Pink url(sprite.png) no-repeat;
  height: 27px;
  position: absolute;
  width: 27px;
}
#images #top-left {
  left: 0;
  top: 0;
}
#images #top-right {
  background-position: 0 -50px;
  right: 0;
  top: 0;
}
#images #bot-right {
  background-position: 0 -100px;
  right: 0;
  bottom: 0;
}
#images #bot-left {
  background-position: 0 -150px;
  left: 0;
  bottom: 0;
}

See a Demo

The browser compliant way with CSS triangles

This uses pretty much the same technique as the sprite method. Box corners are cut off with CSS triangels rather than elements with background image.

Plusses

  • Works on all browsers
  • No images
  • Looks great

Minuses

  • Load of unsemantic elements
  • Can't be used against a background photo

HTML (same as for the sprite method)

<div class="box" id="triangles">
  <div id="top-left"></div>
  <div id="top-right"></div>
  <div id="bot-right"></div>
  <div id="bot-left"></div>
</div>

And the CSS

#triangles {
  background: #33ffcc;
}
#triangles div {
  width: 0;
  height: 0;
  position: absolute;
}
#triangles #top-left {
  border-top: 27px solid white;
  border-right: 27px solid transparent;
  left: 0;
  top: 0;
}
#triangles #top-right {
  border-top: 27px solid white;
  border-left: 27px solid transparent;
  right: 0;
  top: 0;
}
#triangles #bot-right {
  border-bottom: 27px solid white;
  border-left: 27px solid transparent;
  right: 0;
  bottom: 0;
}
#triangles #bot-left {
  border-bottom: 27px solid white;
  border-right: 27px solid transparent;
  left: 0;
  bottom: 0;
}

See a Demo

The other, browser compliant way with CSS triangles

I figured out a new way of beveling corners with triangles. This can be on a multicolor background.

See a Demo

Here's the same with different color elements, to better illustrate the structure.

See a Demo

Roundup

Where the gradient method is the best of these, lacks it support in lt IE 10 (see the compatibility here). Very small caveat: the bevel is not 100% perfect in Chrome (Mac), look at the left side bevels, looks good on the current Chrome. This is also the only technique that can be applied on non solid color background, added another technique.

The trapezoid method is pretty brilliant! Works on IE8 straight out the box, doesn’t use unsemantic elements, isn’t too hacky, a tiny bit only. I'd use that possibly.

After these two, all other methods are pretty much useless.

There’s also an editors draft of Border Corner Shape that enables us to do beveled corners as easily as rounded corners. But, it's just a draft, and nobody knows will it ever make it to the spec.

Comments would go here, but the commenting system isn’t ready yet, sorry. Tweet me @hiljaa if you want to make a correction etc.

  • © 2021 Antti Hiljá
  • About
  • Follow me in Twatter → @hiljaa
  • All rights reserved yadda yadda.
  • I can put just about anything here, no one reads the footer anyways.
  • console.log('Smash the patriarchy!')
  • I love u!