38

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

I need a border radius like this:

Inset border radius

web-tiki
  • 99,765
  • 32
  • 217
  • 249
Serhiy
  • 4,357
  • 5
  • 37
  • 53

8 Answers8

37

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

Chris Krycho
  • 3,125
  • 1
  • 23
  • 35
11

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>
Umutambyi Gad
  • 4,082
  • 3
  • 18
  • 39
Brett Hayes
  • 253
  • 3
  • 7
7

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>
mymedia
  • 572
  • 6
  • 26
John Lawrence
  • 2,923
  • 17
  • 23
2

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.

Matt Coughlin
  • 18,666
  • 3
  • 46
  • 59
  • even though you said it doesn't work, I had never actually tried this. shame it doesn't work, would have been a good feature imo – Lodder Jun 14 '12 at 13:12
2

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

Christoph
  • 50,121
  • 21
  • 99
  • 128
2

body {
    background: #fff;
}

.div{
 position:relative;
}
.box {
background: #f7f7f7;
height: 178px;
width: 409px;
margin: 25px;
/*padding: 20px;*/
position: relative;
overflow: hidden;
border: 1px solid #ccc;
border-left: 0px;
}
.box:before {
content: "";
display: block;
background: #fff;
position: absolute;
top: -33px;
left: -263px;
width: 300px;
height: 242px;
border-radius: 300px;
border: 1px solid #ccc;
}
<div class="div">
<div class="box"></div>
</div>

</body>
</html>

Example here

Umutambyi Gad
  • 4,082
  • 3
  • 18
  • 39
  • Thank you for this code snippet, which may provide some immediate help. A proper explanation [would greatly improve](//meta.stackexchange.com/q/114762) its educational value by showing *why* this is a good solution to the problem, and would make it more useful to future readers with similar, but not identical, questions. Please [edit] your answer to add explanation, and give an indication of what limitations and assumptions apply. – Toby Speight Jun 20 '17 at 15:54
0

Hmm you could possibly make use of this little trick here to create Inset Border Radius

Then to support transparency you would have to probably add other blocks in between. More or less like the way the old rounded images used to be done; having a span for every corner with the transparent image. And spans on the sides and the top to fill up the empty space. Instead of using images you could use this trick to do it in CSS.

Jon Mifsud
  • 163
  • 2
0

body {
    background: #fff;
}

.div{
 position:relative;
}
.box {
background: #f7f7f7;
height: 178px;
width: 409px;
margin: 25px;
/*padding: 20px;*/
position: relative;
overflow: hidden;
border: 1px solid #ccc;
border-left: 0px;
}
.box:before {
content: "";
display: block;
background: #fff;
position: absolute;
top: -33px;
left: -263px;
width: 300px;
height: 242px;
border-radius: 300px;
border: 1px solid #ccc;
}
<div class="div">
<div class="box"></div>
</div>

</body>
</html>