说明

又是一个练手的小玩意儿,本身没什么技术含量,就是几个不常用的CSS3特性的结合而已。

要点

  • Label标签的for属性
  • 单选框的:check伪类
  • CSS的加号[+]选择器

效果图

原理

通常tab页的交互都是点击tab头然后展示对应的一块内容,这种排他性跟HTML里面的某个原住民很类似,是啥呢?没错!就是单选框组。

单选框组有一个:checked伪类,可以设定单选框被选中后的样式,所以我们要把一组单选框当做tab页的头部么?当然不是,单选框是很固执的,用CSS去感化他是很吃力的,那怎么办呢?

这里就要用到CSS里面的+选择器了[实际上这个选择器我之前从来没用过-_-||],简单来说+选择器就是选择紧跟在某个指定元素后面的另一个指定的元素,具体介绍请看 http://www.w3school.com.cn/cssref/selector_element_plus.asp

Label的for属性是一个很有意思的东西,可以理解为一个遥控器:位于页面底部的一个label标签可以通过for属性来控制页面顶部的一个单选框或者复选框~,是不是很神奇?(噗→_→)

结合以上特点,可以得到一个实现tab页的基本思路:

一个单选按钮后面跟一个lable[tab头],再后面跟上一个div[tab内容块]
用.radio:checked + .tab-header 指定当前tab头的样式
用.radio:checked + .tab-header + .tab-content 指定当前tab内容块的样式

代码

<div class="container">
  <div class="tab-wrapper">
    <!--tab section 1-->
    <input type="radio" name="tab-radio" class="tab-radio" id="tab-radio-1" checked>
    <label for="tab-radio-1" class="tab-handler tab-handler-1">水浒传</label>
    <div class="tab-content tab-content-1">《水浒传》是中国历史上第一部用古白话文写成的歌颂农民起义的长篇章回体版块结构小说,以宋江领导的起义军为主要题材,通过一系列梁山英雄反抗压迫、英勇斗争的生动故事,暴露了北宋末年统治阶级的腐朽和残暴,揭露了当时尖锐对立的社会矛盾和“官逼民反”的残酷现实。按120回本计,前70回讲述各个好汉上梁山,后50回主要为宋江全伙受招安为朝廷效力,以及被奸臣所害。</div>
    <!--tab section 2-->
    <input type="radio" name="tab-radio" class="tab-radio" id="tab-radio-2">
    <label for="tab-radio-2" class="tab-handler tab-handler-2">三国演义</label>
    <div class="tab-content tab-content-2">《三国演义》是中国古典四大名著之一,全名为《三国志通俗演义》。作者是元末明初小说家罗贯中,是中国第一部长篇章回体历史演义小说。描写了从东汉末年到西晋初年之间近105年的历史风云。全书反映了三国时代的政治军事斗争,反映了三国时代各类社会矛盾的转化,并概括了这一时代的历史巨变,塑造了一批叱咤风云的三国英雄人物。</div>
    <!--tab section 3-->
    <input type="radio" name="tab-radio" class="tab-radio" id="tab-radio-3">
    <label for="tab-radio-3" class="tab-handler tab-handler-3">西游记</label>
    <div class="tab-content tab-content-3">《西游记》是中国古典四大名著之一,是由明代小说家吴承恩所创作的中国古代第一部浪漫主义的长篇神魔小说。主要描写了唐朝太宗贞观年间孙悟空、猪八戒、沙僧、白龙马四弟子保护唐僧西行取经,沿途历经九九八十一难,一路降妖伏魔,化险为夷,最后到达西天,取得真经的故事。取材于《大唐三藏取经诗话》和汉族民间传说。 [1] </div>
    <!--tab section 4-->
    <input type="radio" name="tab-radio" class="tab-radio" id="tab-radio-4">
    <label for="tab-radio-4" class="tab-handler tab-handler-4">红楼梦</label>
    <div class="tab-content tab-content-4">《红楼梦》,中国古典四大名著之首,清代作家曹雪芹创作的章回体长篇小说[1] 。早期仅有前八十回抄本流传,八十回后部分未完成且原稿佚失。原名《脂砚斋重评石头记》。程伟元邀请高鹗协同整理出版百二十回全本[2] ,定名《红楼梦》。亦有版本作《金玉缘》。</div>
  </div>
</div>

HTML部分如上,四个区块,四大名著,嘎嘎

html,body{
  height: 100%;
  margin: 0;
  padding: 0;
  background-color: #58596b;
}
.container{
  width: 800px;
  height: 400px;
  margin: 100px auto;
  background-color: #fff;
  box-shadow: 0 1px 3px rgba(0,0,0,.1);
}
.tab-wrapper{
  position: relative;
  width: 800px;
  height: 60px;
  background-color: #33344a;
}
.tab-wrapper .tab-radio{
  display: none;
}
.tab-handler{
  position: relative;
  z-index: 2;
  display: block;
  float: left;
  height: 60px;
  padding: 0 40px;
  color: #717181;
  font-size: 16px;
  line-height: 60px;
  transition: .3s;
  transform: scale(.9);
}
.tab-radio:checked + .tab-handler{
  color: #fff;
  background-color: #e74c3c;
  transform: scale(1);
}
.tab-radio:checked + .tab-handler + .tab-content{
  visibility: visible;
  opacity: 1;
  transform: scale(1);
}
.tab-wrapper .tab-content{
  visibility: hidden;
  position: absolute;
  top: 60px;
  left: 0;
  width: 740px;
  padding: 30px;
  color: #999;
  font-size: 14px;
  line-height: 1.618em;
  background-color: #fff;
  opacity: 0;
  transition: transform .5s, opacity .7s;
  transform: translateY(20px);
}

CSS代码如上,写的很烂,轻喷~
用visibility+opacity来控制元素的显示和隐藏,实际上是为了实现动画效果(此处有装逼的嫌疑),因为display会阻碍transition,而visibility不会,另外也可以用pointer-events+opacity来代替。


代码就上面那些了,另附jsbin地址:http://output.jsbin.com/cicadu/4
在新版opera/chrome/firefox测试完美,safari上面有严重问题,貌似切换了tab之后,tab内容块的样式已经应用了然而却没有生效,目测页面没有重绘?在开发者工具里面将其focus一下才生效,具体原因未知,有哪位大神知道的请不吝赐教。

你可能感兴趣的文章

24 条评论
pomelo · 2015年08月07日

css3新增的:checked选择器确实好用.这样一来就可以纯用css去实现js的效果,不过原来css2就有:hover选择器.我尝试了一下用hover去改写你的代码.有几点和你讨论一下
(1)建议添加: .tab-handler:hover{
cursor: move;
}这样鼠标样式的改变比较贴近用户.
(2)直接看代码:

<!DOCTYPE html>
<html>
<head>
    <title>tab</title>
    <meta charset="utf-8">
    <style type="text/css">
html,body{
  height: 100%;
  margin: 0;
  padding: 0;
  background-color: #58596b;
}
.container{
  width: 800px;
  height: 400px;
  margin: 100px auto;
  background-color: #fff;
  box-shadow: 0 1px 3px rgba(0,0,0,.1);
}
.tab-wrapper{
  position: relative;
  width: 800px;
  height: 60px;
  background-color: #33344a;
}


.tab-handler{
  position: relative;
  z-index: 2;
  display: block;
  float: left;
  height: 60px;
  padding: 0 40px;
  color: #717181;
  font-size: 16px;
  line-height: 60px;
  transition: .3s;
  transform: scale(.9);
}
.tab-handler:hover{
    cursor: move;
}
.tab-handler:hover{
  color: #fff;
  background-color: #e74c3c;
  transform: scale(1);
}
.tab-handler:hover + .tab-content{
  visibility: visible;
  opacity: 1;
  transform: scale(1);
}
.tab-wrapper .tab-content{
  visibility: hidden;


  position: absolute;
  top: 60px;
  left: 0;
  width: 740px;
  padding: 30px;
  color: #999;
  font-size: 14px;
  line-height: 1.618em;
  background-color:#fff;
  opacity: 0;
  transition: transform .5s, opacity .7s;
  transform: translateY(20px);
}
    </style>
  </head>

 <body>


<div class="container">
  <div class="tab-wrapper">
    <!--tab section 1-->
    <label class="tab-handler">水浒传</label>
   <div class="tab-content">《水浒传》是中国历史上第一部用古白话文写成的歌颂农民起义的长篇章回体版块 结构小说</div>
    <!--tab section 2-->
    <label class="tab-handler">三国演义</label>
    <div class="tab-content">《三国演义》是中国古典四大名著之一,</div>
    <!--tab section 3-->
    <label  class="tab-handler">西游记</label>
    <div class="tab-content">《西游记》是中国古典四大名著之一</div>
    <!--tab section 4-->
    <label class="tab-handler">红楼梦</label>
    <div class="tab-content">《红楼梦》,中国古典四大名著之首。</div> 
  </div>
 </div>


 </body>
 </html>

有个问题是如何实现初次加载时给它添加一个默认hover样式.相当于tab-content<水浒传>那个内容栏默认显示.能用纯css解决吗?我试了好半天都没结果.

(3)一般tab组件都是先有nav-tab 用<ul> <li></li> </ul>实现,然后统一把tab-content放在<ul></ul>中,这样有李煜SEO搜索,你看能否用这种结构改变一下.这样以来貌似+兄弟选择器就没法用了 ==.

+1 回复

王刚 作者 · 2015年08月07日

前辈说的这种,交互是不是这样的:鼠标放到对应的tab头上,就显示对应的内容,移开鼠标,就显示第一块的内容。
看看http://output.jsbin.com/gurisu,应该实现了前辈所说的效果,至于让第一个tab默认显示的问题,因为CSS里面貌似没有提供选择一个元素前面的同级元素的选择器,所以这里我取了个巧,给tab-handler设置了float:right,这样就将几个tab-handler视觉上的顺序与DOM结构上的顺序进行了颠倒,进而就可以用CSS来控制”前面“的元素了,默认是最后一个tab高亮,其他的tab触发了hover之后,便用.tab-handler:hover ~ .tab-handler将最后一个tab的高亮去掉~ 第三个问题,DOM结构分离之后,css选择器会鞭长莫及,但是也有折中的办法,正在写demo,稍后奉上

+1 回复

pomelo · 2015年08月07日

nice~

回复

王刚 作者 · 2015年08月07日

多谢前辈支持~ :)

回复

pomelo · 2015年08月07日

我是前端菜鸟,一起探讨学习进步吧0

回复

王刚 作者 · 2015年08月07日

...寒,钻进死胡同了,貌似没找到解决方案,另有一个残缺的:在.tab-handler里面放一个button,然后利用.tab-handler button:focus来解决高亮问题,但是这样做,一旦点了别的地方,button的focus也就掉了~

回复

pomelo · 2015年08月07日

nice~这会儿用手机,等回去了用电脑试一下

回复

ZackDary · 2015年08月07日

你的默认tab 怎么处理, tab的顺序颠倒了

回复

王刚 作者 · 2015年08月07日

可以用float:right;来让元素从右到左排列

回复

ZackDary · 2015年08月07日

如果我的导航tab 不铺满 ,就会颠倒, 会右浮动,

回复

王刚 作者 · 2015年08月07日

对呀,所以我用了百分比,更前卫一点就可以考虑flex布局

回复

ZackDary · 2015年08月08日

球支招, 还行不行,flex;

回复

ZackDary · 2015年08月08日

回复

ZackDary · 2015年08月08日

帮我看下 如何默认显示的俺顺序

回复

王刚 作者 · 2015年08月08日

把.tab-handler的float:left;改成float:right;这样顺序就会倒过来,但是这样整体头部就靠右了,所以需要让几个头部排列开来正好撑满容器,这样就看不出来是偏左还是偏右啦

回复

ZackDary · 2015年08月08日

有没有什么办法不撑满容器,左浮动显示 ,默认按照顺序显示

回复

王刚 作者 · 2015年08月08日

还有其他的办法,比如绝对定位,这样你想怎么排就怎么排,但是不灵活,得一个个写,还有个办法很简单,但是描述起来有点难

回复

王刚 作者 · 2015年08月08日

http://output.jsbin.com/gurisu 你再看看这个,其实只要外面在家一层div并让他float:left;就行了,整体就会靠左,也不必撑满整个宽度了

回复

不写代码的码农 · 2015年08月12日

你可以试试用:target来做tab:http://www.ido321.com/1567.html

回复

王刚 作者 · 2015年08月12日

恩,之前用:target做过,但是局限性比较大。这是另外一个幻灯片效果的DEMO,是用:target实现的:http://segmentfault.com/a/1190000003070878

回复

载入中...
王刚 王刚

1.1k 声望

发布于专栏

优雅的Web

发现Web之美

14 人关注

系列文章