Tabs with Round Out Borders

前几天藤藤在每一练中写了一个《CSS3制作Twitter信息框》效果,酷似Chrome浏览器的tabs效果:

藤藤每日一练——CSS3制作Twitter信息框

从上面的效果图上来看,似乎有点棘手,特别是tabs底部的内凹圆角之处的处理。当初转这个设计图的时候,我们一起都没有思路,后来在css-tricks中找到了一篇类似于这种设计的教程,仔细阅读后才知道其原理。今天稍有空闲,将其教程Tabs with Round Out Borders介绍的方法转译成中文与大家分享。直接不来,只好转述其文章中的思想精髓,希望对大家有所帮助。

CSS3的border-radius出现,让广大Web前端人员制作圆角不在像以前那样苦逼,直接一个属性就能搞定了。但话说回来,border-radius制作一些普通圆角是方便,但制作类似于前面截图所示的圆角效果(这里称为内凹圆角)还是有一定难度的。用来一个更具形像的图来解释,要比我说的更清楚:

HTML Markup

在网站制作过程中,什么样的视觉效果都有可能出现,当然你可以使用图片来制作这一切效果。但在这里不考虑任何图片来实现,而且还想创造一个尽可能简洁的结构(为得是尽可能的更新快,至于会不会比图片快,我也不知道,没测试过),因此需要先创建一个模板:

<ul class="nav nav-tabs" id="myTab">
  <li class="active"><a href="#home">Home</a></li>
  <li><a href="#profile">Profile</a></li>
  <li><a href="#messages">Messages</a></li>
  <li><a href="#settings">Settings</a></li>
</ul>
 
<div class="tab-content">
  <div class="tab-pane active" id="home">...</div>
  <div class="tab-pane" id="profile">...</div>
  <div class="tab-pane" id="messages">...</div>
  <div class="tab-pane" id="settings">...</div>
</div>

这是一个典型的tabs的结构,上面的结构代码来自于Bootstrap中的Tabs部分,如果你还不了解Bootstrap,你可以先点击了解一下。

如何制作底部的内凹圆角效果?

前面也说了,制作前面DEMO所示效果最棘手的问题是如何制作tabs菜单底部的内凹圆角效果,原因是我们无法直接使用border-radius来实现,需要使用别的形状贴出来。为了保证结构的整洁,这里考虑不添加额外的标签,而直接使用元素的伪元素(或者伪类选择器)。如果您还是第一次听说这两个概念,你可以点击这里或者这里进行了解。从本质上说,可以添加额外的标签,通过样式来实现,但是每个元素都可以有“:after”(或“::after”)和“:before”(或“::before”),因此在这里选择了他们而没有添加额外的标签,在四个选项卡中,使用了“<li>”和“<a>”两个元素的“:after”与“:before”。

接下来我们一步一步来看实现的过程:

1、默认状态

默认状态下,li是块状,a是行内元素,为了更好的显示效果,在这两个元素上先暂时添加了border样式:

2、li浮动

将li进行左浮动,列表项相互依靠在旁边,并且缩小了与内部a标签的间距:

3、相同尺寸

如果li内没有任何margin和padding值,那么li和a元素将具有相同尺寸大小

先给以上几步加上一个简单的样式:

.nav:after,
.nav:before {
  content:"";
  display: table;
} 
.nav:after {
  clear:both;
  overflow:hidden;
}
.nav {
  zoom: 1;
}
.nav li {
  list-style: none outside none;
  float: left;
}
.nav li a {
  float: left;
  padding: 10px 40px;
  text-decoration: none;
  color: rgb(220, 225, 233);
  background: rgb(10, 41, 30);
}
.nav .active a {
  background: rgb(220, 225, 233);
  color:rgb(10, 41, 30);
}
.tab-content {
  background: rgb(220, 225, 233);
  color:rgb(10, 41, 30);
  padding: 20px;
}

4、焦点放在一个列表项上

这个时候,我们将列表项放在一个焦点之上,然后来看tabs底部内凹圆角的实现:

5、添加圆

接下来利用a的“:after”和“:before”给每个选项卡添加两个圆,先集中在一个选项卡上看效果:

这里两上圆是直接使用border-radius绘制的圆形(详细的制作方法可以点击和这里)。

接下来看实际代码带来的效果:

.demo {
  width: 660px;
  margin: 20px auto;
} 
.nav:after,
.nav:before {
  content:"";
  display: table;
} 
.nav:after {
  clear:both;
  overflow:hidden;
}
.nav {
  zoom: 1;
}
.nav li {
  list-style: none outside none;
  float: left;
  position: relative;/*这个很重要*/
}
.nav li a {
  float: left;
  padding: 10px 40px;
  text-decoration: none;
  color: rgb(220, 225, 233);
  background: rgb(10, 41, 30);
}
.nav .active a {
  background: rgb(220, 225, 233);
  color:rgb(10, 41, 30);
}

/*制作圆角*/
.nav li a:before,
.nav li a:after {
  content:"";
  position: absolute;
  bottom: 0;
  width: 20px;
  height: 20px;
  border-radius: 10px;
  background: red;
}
.nav li a:before {
  left:-20px; 
}
.nav li a:after {
  right: -20px;
}

.tab-content {
  background: rgb(220, 225, 233);
  color:rgb(10, 41, 30);
  padding: 20px;
}

此时每个列表项的前与后添加了一个圆形:

为了更好的看清楚新添加的圆,暂时在li上添加一个margin样式

接下来将圆形的颜色换成和选项卡颜色一样,并且把当前项的颜色也换回来:

.demo {
  width: 660px;
  margin: 20px auto;
} 
.nav:after,
.nav:before {
  content:"";
  display: table;
} 
.nav:after {
  clear:both;
  overflow:hidden;
}
.nav {
  zoom: 1;
}
.nav li {
  list-style: none outside none;
  float: left;
  position: relative;/*这个很重要*/
}
.nav li a {
  float: left;
  padding: 10px 40px;
  text-decoration: none;
  color: rgb(220, 225, 233);
  background: rgb(10, 41, 30);
}
.nav .active a {
  background: rgb(220, 225, 233);
  color:rgb(10, 41, 30);
}

.nav li a:before,
.nav li a:after {
  content:"";
  position: absolute;
  bottom: 0;
  width: 20px;
  height: 20px;
  border-radius: 10px;
  background: rgb(10, 41, 30);
}

/*设置当前选项卡的圆形背景色*/
.nav .active a:before,
.nav .active a:after {
  background: rgb(220, 225, 233);
}

.nav li a:before {
  left:-20px; 
}
.nav li a:after {
  right: -20px;
}

.tab-content {
  background: rgb(220, 225, 233);
  color:rgb(10, 41, 30);
  padding: 20px;
}

6、添加距形

接下来利用li的“:after”和“:before”给每个选项卡添加两个距形,先集中在一个选项卡上看效果:

同样的,将这效果应用 到每个列表项上:

.demo {
  width: 660px;
  margin: 20px auto;
} 
.nav:after,
.nav:before {
  content:"";
  display: table;
} 
.nav:after {
  clear:both;
  overflow:hidden;
}
.nav {
  zoom: 1;
}
.nav li {
  list-style: none outside none;
  float: left;
  position: relative;/*这个很重要*/
}

/*添加正方形*/
.nav li:before,
.nav li:after {
  content:"";
  position: absolute;
  bottom:0;
  background: red;
  width: 10px;
  height: 10px;
}
.nav li:before {
  left: -10px;
}
.nav li:after {
  right: -10px;
}

.nav li a {
  float: left;
  padding: 10px 40px;
  text-decoration: none;
  color: rgb(220, 225, 233);
  background: rgb(10, 41, 30);
}
.nav .active a {
  background: rgb(220, 225, 233);
  color:rgb(10, 41, 30);
}

.nav li a:before,
.nav li a:after {
  content:"";
  position: absolute;
  bottom: 0;
  width: 20px;
  height: 20px;
  border-radius: 10px;
  background: rgb(10, 41, 30);
}
.nav .active a:before,
.nav .active a:after {
  background: rgb(220, 225, 233);
}
.nav li a:before {
  left:-20px; 
}
.nav li a:after {
  right: -20px;
}

.tab-content {
  background: rgb(220, 225, 233);
  color:rgb(10, 41, 30);
  padding: 20px;
}

这个时候的效如下所示:

从上面的效果图中可以看出,此时的圆形和正方形层级关系并不正确,接下来,我们需要使用z-index来改变他们的层级关系:

.demo {
  width: 660px;
  margin: 20px auto;
} 
.nav:after,
.nav:before {
  content:"";
  display: table;
} 
.nav:after {
  clear:both;
  overflow:hidden;
}
.nav {
  zoom: 1;
}
.nav li {
  list-style: none outside none;
  float: left;
  position: relative;/*这个很重要*/
}

.nav .active {
  z-index: 3;/*当前项在最顶端*/
}

.nav li:before,
.nav li:after {
  content:"";
  position: absolute;
  bottom:0;
  background: red;
  width: 10px;
  height: 10px;
}
.nav li:before {
  left: -10px;
}
.nav li:after {
  right: -10px;
}
.nav li a {
  float: left;
  padding: 10px 40px;
  text-decoration: none;
  color: rgb(220, 225, 233);
  background: rgb(10, 41, 30);
}
.nav .active a {
  background: rgb(220, 225, 233);
  color:rgb(10, 41, 30);
}

.nav li a:before,
.nav li a:after {
  content:"";
  position: absolute;
  bottom: 0;
  width: 20px;
  height: 20px;
  border-radius: 10px;
  background: rgb(10, 41, 30);
  z-index: 2;/*圆形在矩形上面*/
}
.nav .active a:before,
.nav .active a:after {
  background: rgb(220, 225, 233);
}
.nav li a:before {
  left:-20px; 
}
.nav li a:after {
  right: -20px;
}

/*当前项的:after和:before的z-index值为1*/
.nav .active:before,
.nav .active:after {
  z-index: 1;/*当前项的矩形在圆形下面*/
}

.tab-content {
  background: rgb(220, 225, 233);
  color:rgb(10, 41, 30);
  padding: 20px;
}

将颜色换正:

.demo {
  width: 660px;
  margin: 20px auto;
} 
.nav:after,
.nav:before {
  content:"";
  display: table;
} 
.nav:after {
  clear:both;
  overflow:hidden;
}
.nav {
  zoom: 1;
}
.nav li {
  list-style: none outside none;
  float: left;
  position: relative;/*这个很重要*/
}
.nav .active {
  z-index: 3;/*当前项在最顶端*/
}
.nav li:before,
.nav li:after {
  content:"";
  position: absolute;
  bottom:0;
  background: rgb(10, 41, 30);
  width: 10px;
  height: 10px;
}
.nav li:before {
  left: -10px;
}
.nav li:after {
  right: -10px;
}
.nav li a {
  float: left;
  padding: 10px 40px;
  text-decoration: none;
  color: rgb(220, 225, 233);
  background: rgb(10, 41, 30);
}
.nav .active a {
  background: rgb(220, 225, 233);
  color:rgb(10, 41, 30);
}

.nav li a:before,
.nav li a:after {
  content:"";
  position: absolute;
  bottom: 0;
  width: 20px;
  height: 20px;
  border-radius: 10px;
  background: rgb(10, 41, 30);
  z-index: 2;/*圆形在矩形上面*/
}
.nav .active a:before,
.nav .active a:after {
  background: rgb(220, 225, 233);
}
.nav li a:before {
  left:-20px; 
}
.nav li a:after {
  right: -20px;
}
/*当前项的:after和:before的z-index值为1*/
.nav .active:before,
.nav .active:after {
  z-index: 1;/*当前项的矩形在圆形下面*/
  background: rgb(220, 225, 233);
}
.tab-content {
  background: rgb(220, 225, 233);
  color:rgb(10, 41, 30);
  padding: 20px;
}

此时的效果就越来越接近我们需要了:

上面的效果离我们最终效果仅仅就差那么一顶点,效果图明显告诉我们,当前项的圆形背景色不能与相邻的其它选项容合,那么这一点很好办,我们只要将其背景色换成相邻选项卡的背景色一样就Ok了:

.demo {
  width: 660px;
  margin: 20px auto;
} 
.nav:after,
.nav:before {
  content:"";
  display: table;
} 
.nav:after {
  clear:both;
  overflow:hidden;
}
.nav {
  zoom: 1;
}
.nav li {
  list-style: none outside none;
  float: left;
  position: relative;/*这个很重要*/
}
.nav .active {
  z-index: 3;/*当前项在最顶端*/
}
.nav li:before,
.nav li:after {
  content:"";
  position: absolute;
  bottom:0;
  background: rgb(10, 41, 30);
  width: 10px;
  height: 10px;
}
.nav li:before {
  left: -10px;
}
.nav li:after {
  right: -10px;
}
.nav li a {
  float: left;
  padding: 10px 40px;
  text-decoration: none;
  color: rgb(220, 225, 233);
  background: rgb(10, 41, 30);
}
.nav .active a {
  background: rgb(220, 225, 233);
  color:rgb(10, 41, 30);
}

.nav li a:before,
.nav li a:after {
  content:"";
  position: absolute;
  bottom: 0;
  width: 20px;
  height: 20px;
  border-radius: 10px;
  background: rgb(10, 41, 30);
  z-index: 2;/*圆形在矩形上面*/
}
.nav .active a:before,
.nav .active a:after {
  background: rgb(10, 41, 30);
}
.nav li a:before {
  left:-20px; 
}
.nav li a:after {
  right: -20px;
}
/*当前项的:after和:before的z-index值为1*/
.nav .active:before,
.nav .active:after {
  z-index: 1;/*当前项的矩形在圆形下面*/
  background: rgb(220, 225, 233);
}
.tab-content {
  background: rgb(220, 225, 233);
  color:rgb(10, 41, 30);
  padding: 20px;
}

还有一个明显的问题,那就是第一个选 项卡和最后一个选项卡,圆形背景色没有处理,那么我们按同样的方法将其处理。

.demo {
  width: 660px;
  margin: 20px auto;
} 
.nav:after,
.nav:before {
  content:"";
  display: table;
} 
.nav:after {
  clear:both;
  overflow:hidden;
}
.nav {
  zoom: 1;
}
.nav li {
  list-style: none outside none;
  float: left;
  position: relative;/*这个很重要*/
}
.nav .active {
  z-index: 3;/*当前项在最顶端*/
}
.nav li:before,
.nav li:after {
  content:"";
  position: absolute;
  bottom:0;
  background: rgb(10, 41, 30);
  width: 10px;
  height: 10px;
}
.nav li:before {
  left: -10px;
}
.nav li:after {
  right: -10px;
}
.nav li a {
  float: left;
  padding: 10px 40px;
  text-decoration: none;
  color: rgb(220, 225, 233);
  background: rgb(10, 41, 30);
}
.nav .active a {
  background: rgb(220, 225, 233);
  color:rgb(10, 41, 30);
}

.nav li a:before,
.nav li a:after {
  content:"";
  position: absolute;
  bottom: 0;
  width: 20px;
  height: 20px;
  border-radius: 10px;
  background: rgb(10, 41, 30);
  z-index: 2;/*圆形在矩形上面*/
}
.nav .active a:before,
.nav .active a:after {
  background: rgb(10, 41, 30);
}
.nav li a:before {
  left:-20px; 
}
.nav li a:after {
  right: -20px;
}
/*当前项的:after和:before的z-index值为1*/
.nav .active:before,
.nav .active:after {
  z-index: 1;/*当前项的矩形在圆形下面*/
  background: rgb(220, 225, 233);
}

/*第一个选项卡的:before和最后一个选项卡的:after背景色不一样*/
.nav li:first-child a:before,
.nav li:last-child a:after {
  background-color: #fff;
}

.tab-content {
  background: rgb(220, 225, 233);
  color:rgb(10, 41, 30);
  padding: 20px;
}

底部内凹圆角效果,可算是完成了,为了让效果更佳完美,给每个选项卡顶部加上圆角效果,并且将选项卡向右移动些许px:

.demo {
  width: 660px;
  margin: 20px auto;
} 
.nav:after,
.nav:before {
  content:"";
  display: table;
} 
.nav:after {
  clear:both;
  overflow:hidden;
}
.nav {
  zoom: 1;
  margin-left: 20px;
}
.nav li {
  list-style: none outside none;
  float: left;
  position: relative;/*这个很重要*/
}
.nav .active {
  z-index: 3;/*当前项在最顶端*/
}
.nav li:before,
.nav li:after {
  content:"";
  position: absolute;
  bottom:0;
  background: rgb(10, 41, 30);
  width: 10px;
  height: 10px;
}
.nav li:before {
  left: -10px;
}
.nav li:after {
  right: -10px;
}
.nav li a {
  float: left;
  padding: 10px 40px;
  text-decoration: none;
  color: rgb(220, 225, 233);
  background: rgb(10, 41, 30);
  border-radius: 10px 10px 0 0;/*给选项卡顶部添加圆角效果*/
}
.nav .active a {
  background: rgb(220, 225, 233);
  color:rgb(10, 41, 30);
}

.nav li a:before,
.nav li a:after {
  content:"";
  position: absolute;
  bottom: 0;
  width: 20px;
  height: 20px;
  border-radius: 10px;
  background: rgb(10, 41, 30);
  z-index: 2;/*圆形在矩形上面*/
}
.nav .active a:before,
.nav .active a:after {
  background: rgb(10, 41, 30);
}
.nav li a:before {
  left:-20px; 
}
.nav li a:after {
  right: -20px;
}
/*当前项的:after和:before的z-index值为1*/
.nav .active:before,
.nav .active:after {
  z-index: 1;/*当前项的矩形在圆形下面*/
  background: rgb(220, 225, 233);
}
/*第一个选项卡的:before和最后一个选项卡的:after背景色不一样*/
.nav li:first-child a:before,
.nav li:last-child a:after {
  background-color: #fff;
}
.tab-content {
  background: rgb(220, 225, 233);
  color:rgb(10, 41, 30);
  padding: 20px;
}

此时的效果就完美了:

最终css代码:

.demo {
  width: 660px;
  margin: 20px auto;
} 
.nav:after,
.nav:before {
  content:"";
  display: table;
} 
.nav:after {
  clear:both;
  overflow:hidden;
}
.nav {
  zoom: 1;
  margin-left: 20px;
}
.nav li {
  list-style: none outside none;
  float: left;
  position: relative;/*这个很重要*/
}
.nav .active {
  z-index: 3;/*当前项在最顶端*/
}
.nav li:before,
.nav li:after,
.nav  a:before,
.nav  a:after {
  content:"";
  position: absolute;
  bottom:0;

}
.nav li:before,
.nav li:after {
  background: rgb(10, 41, 30);
  width: 10px;
  height: 10px;
}
.nav li:before {
  left: -10px;
}
.nav li:after {
  right: -10px;
}
.nav a {
  float: left;
  padding: 10px 40px;
  text-decoration: none;
  color: rgb(220, 225, 233);
  background: rgb(10, 41, 30);
  border-radius: 10px 10px 0 0;
}
.nav .active a {
  background: rgb(220, 225, 233);
  color:rgb(10, 41, 30);
}

.nav  a:before,
.nav  a:after {
  width: 20px;
  height: 20px;
  border-radius: 10px;
  background: rgb(10, 41, 30);
  z-index: 2;/*圆形在矩形上面*/
}
.nav .active a:before,
.nav .active a:after {
  background: rgb(10, 41, 30);
}
.nav  a:before {
  left:-20px; 
}
.nav  a:after {
  right: -20px;
}
/*当前项的:after和:before的z-index值为1*/
.nav .active:before,
.nav .active:after {
  z-index: 1;/*当前项的矩形在圆形下面*/
  background: rgb(220, 225, 233);
}
/*第一个选项卡的:before和最后一个选项卡的:after背景色不一样*/
.nav li:first-child a:before,
.nav li:last-child a:after {
  background-color: #fff;
}
.tab-content {
  background: rgb(220, 225, 233);
  color:rgb(10, 41, 30);
  padding: 20px;
}

7、添加JavaScript代码:

为了效果更像tabs选项卡效果,直接将BootstrapTabs效果用上来:

<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="bootstrap-tab.js"></script>
<script type="text/javascript">
  $(function(){
    $('#myTab a').click(function (e) {
      e.preventDefault();
      $(this).tab('show');
    })
  });
</script>

同时加上对应的tabs同内容的样式:

.tab-pane {
  display: none;
}
.tab-pane.active {
  display: block;
}

这样一来,我们就算是大功告成了,最终效果可以点击下面的demo:

那么这个效果制作过程就算是完成了,不知道你有没有整清楚。如果没有整清楚的话不仿动手一试。

特别感谢css-tricks提供的敏捷思路——Tabs with Round Out Borders,不过这个效果还不是最佳效果,离我们最开始截的浏览器窗口效果还略有差别,不过大家放心,后面还有一个完善版本。如果您对这个感兴趣的,请观注本站的相关更新。

如需转载,烦请注明出处:http://www.w3cplus.com/css3/tabs-with-round-out-borders.html

返回顶部