Inset border-radius with CSS3

The best way I've found to achieve this with all CSS and HTML (no images, etc.) is by using CSS3 gradients, per Lea Verou. From her solution:

div.round {
    background:
        -moz-radial-gradient(0 100%, circle, rgba(204,0,0,0) 14px, #c00 15px),
        -moz-radial-gradient(100% 100%, circle, rgba(204,0,0,0) 14px, #c00 15px),
        -moz-radial-gradient(100% 0, circle, rgba(204,0,0,0) 14px, #c00 15px),
        -moz-radial-gradient(0 0, circle, rgba(204,0,0,0) 14px, #c00 15px);
    background:
            -o-radial-gradient(0 100%, circle, rgba(204,0,0,0) 14px, #c00 15px),
            -o-radial-gradient(100% 100%, circle, rgba(204,0,0,0) 14px, #c00 15px),
            -o-radial-gradient(100% 0, circle, rgba(204,0,0,0) 14px, #c00 15px),
            -o-radial-gradient(0 0, circle, rgba(204,0,0,0) 14px, #c00 15px);
    background:
            -webkit-radial-gradient(0 100%, circle, rgba(204,0,0,0) 14px, #c00 15px),
            -webkit-radial-gradient(100% 100%, circle, rgba(204,0,0,0) 14px, #c00 15px),
            -webkit-radial-gradient(100% 0, circle, rgba(204,0,0,0) 14px, #c00 15px),
            -webkit-radial-gradient(0 0, circle, rgba(204,0,0,0) 14px, #c00 15px);
    background-position: bottom left, bottom right, top right, top left;
        -moz-background-size: 50% 50%;
        -webkit-background-size: 50% 50%;
    background-size: 50% 50%;
    background-repeat: no-repeat;
}

The net result is a set of transparent gradients with curves. See the full JSFiddle for a demo and to play around with the way it looks.

Obviously this depends on support for rgba and gradient, and accordingly should be treated as a progressive enhancement, or if it's essential to the design, you should supply an image-based fallback for older browsers (especially IE, which doesn't support gradient even up through IE9).


You can achieve this by absolutely positioning transparent circle elements in the corners with box shadows. I used a combination of hidden overflowed divs containing spans, box shadows, borders, and pseudo selectors.

Check out my example.

This is the basic HTML and CSS you need to get started:

a {
  display: inline-block;
  width: 250px;
  height: 100px;
  background: #ccc;
  border: 2px solid #000;
  position: relative;
  margin: 10px;
}

a div {
  position: absolute;
  top: 0;
  overflow: hidden;
  width: 15px;
  height: 100%;
}

a div:after {
  content: '';
  background: #000;
  width: 2px;
  height: 75px;
  position: absolute;
  top: 12.5px;
}

a div:first-of-type {
  left: -14px;
}

a div:first-of-type:after {
  left: 0;
}

a div:last-of-type {
  right: -14px;
}

a div:last-of-type:after {
  right: 0;
}

a span {
  display: block;
  width: 30px;
  height: 30px;
  background: transparent;
  position: absolute;
  bottom: -20px;
  right: -20px;
  border: 2px solid #000;
  border-radius: 25px;
  box-shadow: 0 0 0 60px #ccc;
}

a div:first-of-type span {
  left: -20px;
}

a div:first-of-type span:first-child {
  top: -20px;
}

a div:first-of-type span:last-child {
  bottom: -20px;
}

a div:last-of-type span {
  right: -20px;
}

a div:last-of-type span:first-child {
  top: -20px;
}

a div:last-of-type span:last-child {
  bottom: -20px;
}
<a href="">
  <div>
    <span></span>
    <span></span>
  </div>

  <div>
    <span></span>
    <span></span>
  </div>
</a>

I don't think that it would be possible if the corners have to be transparent, however if the background is known, you can create a div in each corner with a rounded border. If those divs are then given the same background color as the page background the effect will work.

See my example here http://jsfiddle.net/TdDtX/

#box {
    position: relative;
    margin: 30px;
    width: 200px;
    height: 100px;
    background: #ccc;
    border: 1px solid #333;
}

.corner {
    position: absolute;
    height: 10px;
    width: 10px;
    border: 1px solid #333;
    background-color: #fff;
}

.top-left {
    top: -1px;
    left: -1px;
    border-radius: 0 0 100% 0;
    border-width: 0 1px 1px 0;
}

.top-right {
    top: -1px;
    left: 190px;
    border-radius: 0 0 0 100%;
    border-width: 0 0 1px 1px;
}

.bottom-left {
    top: 90px;
    left: -1px;
    border-radius: 0 100% 0 0;
    border-width: 1px 1px 0 0;
}

.bottom-right {
    top: 90px;
    left: 190px;
    border-radius: 100% 0 0 0;
    border-width: 1px 0 0 1px;
}
<div id="box">
    <div class="corner top-left"></div>
    <div class="corner top-right"></div>
    <div class="corner bottom-left"></div>
    <div class="corner bottom-right"></div>
</div>

Tags:

Css

Css Shapes