10

I am trying to create an inner curved border for active/selected menu. Below snippet is so far the best I can do, the square corner shouldn't be visible. Solutions from google doesn't seem to help... Please help me play with it. Thanks guys!

FIDDLE HERE.

body {
  background:#eee;width:90%;margin:20px auto
}
ul {
  margin: 0;
  padding: 0;
}
ul li {
  display: inline-block;
  list-style: none;
  position: relative;
  vertical-align:bottom;
}
ul li a {
  padding: 10px 15px;
  display: block;
  line-height: 25px;
  margin-bottom:-1px;
}
ul li.active a {
  background:#fff;
  border:1px solid #aaa;
  border-bottom:0;
  border-radius:5px 5px 0 0;
}

ul li.active:before,
ul li.active:after {
  content:"";
  position:absolute;
  bottom:-1px;
  width:10px;
  height:10px;
  border:solid #aaa;
}
ul li.active:before {
  left:-10px;
  border-radius:8px 0;
  border-width:0 1px 1px 0
}
ul li.active:after {
  right:-10px;
  border-radius: 0 8px;
  border-width:0 0 1px 1px;
}

.content {
  border:1px solid #aaa;background:#fff;height:200px
}
<ul>
    <li><a href="#">tab 1</a></li>
    <li class="active"><a href="#">tab2</a></li>
    <li><a href="#">tab3</a></li>
    <li><a href="#">tab4</a></li>
</ul>
<div class="content"></div>
web-tiki
  • 99,765
  • 32
  • 217
  • 249
jamez88
  • 585
  • 2
  • 15
  • You might find [this similar question](http://stackoverflow.com/questions/4601317/css-to-create-curved-corner-between-two-elements/10364318#10364318) interesting enough... – jbutler483 Apr 13 '15 at 10:40
  • I've seen those. But most of the solutions found in google doesn't support borders. Usually, they used the borders to create gap instead. :) – jamez88 Apr 13 '15 at 11:17

4 Answers4

8

This is my solution so far. But I am hoping there is a better solution out there... I use the pseudo element of active a to create a white border to hide the sharp corner.

body {
  background:#eee;width:90%;margin:20px auto
}
ul {
  margin: 0;
  padding: 0;
}
ul li {
  display: inline-block;
  list-style: none;
  position: relative;
  vertical-align:bottom;
}
ul li a {
  padding: 10px 15px;
  display: block;
  line-height: 25px;
  margin-bottom:-1px;
}
ul li.active a {
  background:#fff;
  border:1px solid #aaa;
  border-bottom:0;
  border-radius:5px 5px 0 0;
}

ul li.active:before,
ul li.active:after {
  content:"";
  position:absolute;
  bottom:-1px;
  width:10px;
  height:10px;
  border:solid #aaa;
}
ul li.active:before {
  left:-10px;
  border-radius:50% 0;
  border-width:0 1px 1px 0;
  box-shadow: 1px 1px white;
}
ul li.active:after {
  right:-10px;
  border-radius: 0 50%;
  border-width:0 0 1px 1px;
  box-shadow: -1px 1px white;
}

.content {
  border:1px solid #aaa;background:#fff;height:200px
}
<ul>
    <li><a href="#">tab 1</a></li>
    <li class="active"><a href="#">tab2</a></li>
    <li><a href="#">tab3</a></li>
    <li><a href="#">tab4</a></li>
</ul>
  <div class="content"></div>

UPDATE: My previous answer requires more css so I edited it. Based on the answer of jbutler, I got the idea about adding box-shadow to hide the corners. Nothing much changed on the original css I presented here, I just added the box-shadow. Updated fiddle HERE.

jamez88
  • 585
  • 2
  • 15
5

You can try using a white square block :before and :after the li.active a element, and positioning it so it's between the radius and the li:

ul li.active a:before,
ul li.active a:after {
  content: "";
  position: absolute;
  background-color: white;
  height: 11px;
  width: 10px;
  bottom: -1px;
}

ul li.active a:before {
  left: -6px;
  z-index: 1;
}
ul li.active a:after {
  right: -6px;
  background-color: white;
  z-index: 6;
}

ul li.active:before {
  left:-10px;
  border-radius:8px 0;
  border-width:0 1px 1px 0;
  z-index: 5; // <<< This too
}
ul li.active:after {
  right:-10px;
  border-radius: 0 8px;
  border-width:0 0 1px 1px;
  z-index: 10; // <<< And here
}

http://jsfiddle.net/be5ceL9z/4/

This essentially just covers the square bottom corners of the li.active and #content elements by manipulating little square elements to cover them, but to be under the border-radius'd li.active:before and :after.

A more thorough explanation (courtesy atomictom's answer):

https://css-tricks.com/tabs-with-round-out-borders/

Jared Farrish
  • 48,585
  • 17
  • 95
  • 104
2

Here is an example of how this could be achieved with a combination of rotation and box shadows:

Initially, you have your rectangular div/element:

    +---------+
    | ELEMENT |
    +---------+

From that, you can position a pseudo element either side of the bottom corners, with a border radius of 50% (to make a circle)

    +---------+
    | ELEMENT |
   O+---------+O

Because I haven't set a background colour, you won't see this.

I've set a border on both, but then set three of the side colours to 'transparent' (so you only see one border).

Rotating this means that you can make the 'curved corner border' for each side:

    +---------+
    | ELEMENT |
   )+---------+(

Using a box shadow then means you can hide the 'elements bottom corner' anyway:

    +---------+
    | ELEMENT |
   ) --------- (

Then setting the bottom border color to the active elelemtn itself means it is then 'hidden' anyway:

    +---------+
    | ELEMENT |
    )         ( <-- rotated slightly to create your corner


DEMO

/*FOR DEMO ONLY*/


$(document).ready(function() {
  $('.menu div').click(function() {
    $('.menu div').removeClass("act");
    $(this).addClass("act");
  });
});
html {
  background: lightgray;
}
.menu div {
  display: inline-block;
  height: 50px;
  width: 100px;
  background: white;
  margin: 10px;
  position: relative;
  text-align: center;
  border-radius: 10px 10px 0 0;
  border: 2px solid black;
  cursor:pointer;
}
.menu .act {
  border-bottom-color: white;
  z-index: 40;
}
.act:before,
.act:after {
  content: "";
  position: absolute;
  bottom: -2px;
  height: 20px;
  width: 20px;
  border-radius: 50%;
  border: 2px solid transparent;
  z-index: 30;
}
.act:before {
  left: 100%;
  border-left-color: black;
  -webkit-transform: rotate(-40deg);
  -moz-transform: rotate(-40deg);
  transform: rotate(-40deg);
  box-shadow: -20px 2px 0 0 white;
}
.act:after {
  right: 100%;
  border-right-color: black;
  -webkit-transform: rotate(40deg);
  -moz-transform: rotate(40deg);
  transform: rotate(40deg);
  box-shadow: 20px 2px 0 0 white;
}
.panel {
  width: 80vw;
  margin-top: -12px;
  background: white;
  border-top: 2px solid black;
  z-index: 20;
  padding-top: 12px;
  position: relative;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="menu">
  <div>1</div>
  <div class="act">2</div>
  <div>3</div>
</div>

<div class="panel">Don't you wish Tabs could just be easy?</div>

Note

the jquery included here is for demo only, and shows how you can 'switch tabs'.

jbutler483
  • 24,074
  • 9
  • 92
  • 145
  • Thanks! I'll try to dissect your answer and see if I can apply to all my projects :) – jamez88 Apr 13 '15 at 11:21
  • @jamez88: if there's anything you're not sure about, feel free to ask. (I'll try editing to include explanation soon) – jbutler483 Apr 13 '15 at 11:24
  • Yup got that. I'll try to implement it to my current markup. Your answer seems better because I do not have to use the pseudo element of "a" as seen on my answer.. – jamez88 Apr 13 '15 at 11:50
  • thanks about the idea of adding box-shadow. I updated my answer. No need to rotate, I just position the angle of the box-shadow to the corner. – jamez88 Apr 13 '15 at 12:37
1

I'd just comment but I'm not allowed.. Is this the effect you're after?

https://css-tricks.com/tabs-with-round-out-borders/

Looks like you need another psuedo element.

atomictom
  • 1,637
  • 16
  • 14