写代码前的准备
1、复习一下CSS选择器:
CSS选择器详解(一)
CSS选择器详解(二·伪类)
一般来说,使用纯CSS实现Tab页面效果的常用方式是a标签和:target结合,但是这样实现有一个强迫症的地方:由于是使用a标签把页面“链接”到某个指定ID的元素上,因此浏览器的URL里会出现[#ID]的情况。而且,使用a标签也不好控制Tab导航按钮选中后的样式。
一组Tab标签页面可以看做是一组互斥的按钮:反正我每次都只能有一个按钮处于选中的状态。是不是觉得这个性质就像某个熟悉的html元素?对,就是单选按钮啊!单选按钮有一个伪类是:checked,更方便调整按钮选中后的样式啊!
所以这篇博客采用的方式是:
HTML: <input type="radio" />
CSS: xxx:checked{}
单层Tab实现
实现思路
有了开头部分的提示,思路应该就比较清晰了:使用一组radio button,选中某个选项的时候就展示这个选项对应的页面。
那么问题来了,咱们都知道,radio button自带的样式(小灰圈中间一个点)简直丑哭,不同的浏览器还有不同的渲染效果,而且很明显,想要拿CSS把这个丑哭的小灰圈感动成大方框中间还带字儿的那种效果显然不容易啊。不怕,网上那么多的美好的单选按钮样式也不是只能出现在设计师们的PSD中的啊,是时候拿出lable标签这个大法宝了。
<lable>
: 定义和用法
<label>
标签为 input 元素定义标注(标记)。
<label>
元素不会向用户呈现任何特殊效果。不过,它为鼠标用户改进了可用性。如果您在< label>
元素内点击文本,就会触发此控件。就是说,当用户选择该标签时,浏览器就会自动将焦点转到和标签相关的表单控件上。
<label>
标签的 for 属性应当与相关元素的 id 属性相同。
也就是说,我们可以通过<lable>
标签的for属性,把<lable>
和对应的单选按钮绑定起来,通过点击<lable>
标签来改变单选按钮的选中和取消状态,通过给<lable>
添加样式来实现美化按钮的效果。
那么问题又来了,单选按钮的样式问题解决了,那该怎么把每个Tab下要显示的内容和单选按钮联系起来?很简单,有一个神奇的选择器:
相邻元素选择器 +
效果图
代码
代码全放上来啦,偷懒的小伙伴们直接复制粘贴就可以用啦。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>纯CSS实现双层tab</title>
<style >
.container{
background-color: #2cb0a2;
height: 300px;
width: 500px;
margin: 50px auto;
padding: 30px;
color: white;
border-radius: 10px;
box-shadow: 10px 30px 20px #ccc;
}
.tab-container{
position: relative;
}
.tab-radio{
display: none;
}
.tab-lable{
display: inline-block;
height: 50px;
width: 100px;
line-height: 50px;
margin:0;
text-align: center;
background-color: rgba(255,255,255,0.5);
}
.content{
position: absolute;
visibility: hidden;
top: 40px;
left: 0;
width: 435px;
padding: 30px;
color: white;
font-size: 14px;
background-color: rgba(255,255,255,0.5);
transition: transform .5s, opacity .7s;
transform: translateY(20px);
}
.tab-radio:checked + .tab-lable + .content{
visibility: visible;
}
.tab-radio:checked + .tab-lable{
background-color: rgba(255,255,255,0.2);
}
</style>
</head>
<body>
<div class="container">
<div class="tab-container">
<input type="radio" name="name" value="" id="tab-btn-1" class="tab-radio" checked="checked"/>
<label for="tab-btn-1" class="tab-lable">tab1</label>
<div class="content">
我是第一个tab
</div>
<input type="radio" name="name" value="" id="tab-btn-2" class="tab-radio"/>
<label for="tab-btn-2" class="tab-lable">tab2</label>
<div class="content">
我是第二个tab
</div>
<input type="radio" name="name" value="" id="tab-btn-3" class="tab-radio"/>
<label for="tab-btn-3" class="tab-lable">tab3</label>
<div class="content">
我是第三个tab
</div>
</div>
</div>
</body>
</html>
双层Tab实现
实现思路
实现了单层的Tab之后再去实现双层的似乎很容易:给第一层的Tab内容页里嵌套上第二层的就好了嘛。
事实也很容易,确实是这样,不过有个小小的坑:第一层的tab内容页我是先使用的visibility:visible
把内容页隐藏了起来,当对应的radio button 选中时再把它的visibility设置为显示。也就是说,正常情况下,一个tab页面的子tab页面应该是随着这个tab页面一起出现或者隐藏,但是如果子tab页面组用的也是visibility,就会出现这种情况:
子Tab的内容页在应该消失的地方并没有消失,原因是切换到tab2后,子Tab2仍然处于选中状态,虽然它的父容器的visibility是hidden,可是它的visibility被重新设置为visible。
解决方法就是把原本使用visibility隐藏和显示元素的地方换做display,visibility: hidden的时候虽然元素看不到了,但是它依然在占据着位置,display: none的时候,元素相当于从当前位置被移除,带着它的子元素一起被移除。
效果图
代码
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>纯CSS实现双层tab</title>
<style >
.container{
background-color: #2cb0a2;
height: 300px;
width: 500px;
margin: 50px auto;
padding: 30px;
color: white;
border-radius: 10px;
box-shadow: 10px 30px 20px #ccc;
}
.tab-container{
position: relative;
}
.tab-radio, .tab-sm-radio{
display: none;
}
.tab-lable, .tab-sm-lable{
display: inline-block;
height: 50px;
width: 100px;
line-height: 50px;
margin:0;
text-align: center;
background-color: rgba(255,255,255,0.5);
}
.tab-sm-lable{
color: #666;
}
.content, .sm-content{
position: absolute;
/*visibility: hidden;*/
display: none;
top: 40px;
left: 0;
width: 435px;
padding: 30px;
color: white;
font-size: 14px;
background-color: rgba(255,255,255,0.5);
transition: transform .5s, opacity .7s;
transform: translateY(20px);
}
.sm-content{
top: 90px;
}
.tab-radio:checked + .tab-lable + .content, .tab-sm-radio:checked + .tab-sm-lable + .sm-content{
/*visibility: visible;*/
display: block;
}
.tab-radio:checked + .tab-lable, .tab-sm-radio:checked + .tab-sm-lable{
background-color: rgba(255,255,255,0.3);
}
</style>
</head>
<body>
<div class="container">
<div class="tab-container">
<input type="radio" name="name" value="" id="tab-btn-1" class="tab-radio" checked="checked"/>
<label for="tab-btn-1" class="tab-lable">tab1</label>
<div class="content">
<input type="radio" name="name-sm" value="" id="tab-sm-btn-1" class="tab-sm-radio" checked="checked"/>
<label for="tab-sm-btn-1" class="tab-sm-lable">子Tab1</label>
<div class="sm-content">
子Tab1内容
</div>
<input type="radio" name="name-sm" value="" id="tab-sm-btn-2" class="tab-sm-radio"/>
<label for="tab-sm-btn-2" class="tab-sm-lable">子Tab2</label>
<div class="sm-content">
子Tab2内容
</div>
<input type="radio" name="name-sm" value="" id="tab-sm-btn-3" class="tab-sm-radio"/>
<label for="tab-sm-btn-3" class="tab-sm-lable">子Tab3</label>
<div class="sm-content">
子Tab3内容
</div>
</div>
<input type="radio" name="name" value="" id="tab-btn-2" class="tab-radio"/>
<label for="tab-btn-2" class="tab-lable">tab2</label>
<div class="content">
我是第二个tab
</div>
<input type="radio" name="name" value="" id="tab-btn-3" class="tab-radio"/>
<label for="tab-btn-3" class="tab-lable">tab3</label>
<div class="content">
我是第三个tab
</div>
</div>
</div>
</body>
</html>
提供一个更懒的方式,直接去github下代码:PM’s github