Inset border-radius with CSS3

Is there way to create inset border radius with css3? (Without images)

I need a border radius like this:

Inset border radius


Solution 1:

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).

Solution 2:

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>

Solution 3:

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>

Solution 4:

You could achieve this effect with the new css3-Border-images (well, it's images, but it scales without problems). But this is quite new and not very widely supported yet (well in all decent browsers (with prefixes) except IE to be precise;) ).

A nice article about border images on csstricks.

Browser Support

Solution 5:

It doesn't look like that's possible. I tried a border-radius with a negative value just to see what would happen but it had no effect.

Edit:

Even if you break the box down into smaller parts, at some point you'd still have to create a transparent inset corner. The transparency is the tricky part that might prevent this from being possible without images. Basically, you'd have to be able to render a transparent circle with a non-transparent surrounding bg (and if that's possible in CSS, I'd love to know how :)

If you don't need transparency, there are ways to do it.