用纯css实现Tab切换

简介: 用纯css实现Tab切换

我们今天用css来实现一个常见的tab切换效果

查看原文可以有更好的排版效果哦


先看效果

https://codepen.io/xboxyan/pe...点击预览


前言


哪些简单的效果可以考虑用css来实现呢,目前css能够做的交互有

  • 鼠标经过/离开:hover
  • 鼠标点击::cheked


那是不是上述所有的交互都可以用css来实现呢?显然不是的,css实现依赖于html结构,因为css选择器有限,有子选择器,没有父选择器,有后选择器,没有前选择器,所以局限性很大。所以当我们思考能否用css来实现时还应考虑到html的结构,能不能构造出满足css已存在的选择器的html布局。

先从html结构说起


一般在碰到tab类型的组件时,一般会有如下的html

<div class="tabs">
  <div class="tab-nav">
    <div class="tab-item">tab01</div>
    <div class="tab-item">tab02</div>
    <div class="tab-item">tab03</div>
  </div>
  <div class="tab-content">
    <div>111</div>
    <div>222</div>
    <div>333</div>
  </div>
</div>


大致就是这种布局吧,暂且称作分离模式吧,足够灵活,就是导航部分和内容结构分开,需要什么动画效果都可以分别实现。

还有一种布局,大概是这样的

<div class="tabs">
  <div class="tab-pane">
    <div class="tab-item">tab01</div>
    <div class="tab-content">111</div>
  </div>
  <div class="tab-pane">
    <div class="tab-item">tab01</div>
    <div class="tab-content">111</div>
  </div>
  <div class="tab-pane">
    <div class="tab-item">tab01</div>
    <div class="tab-content">111</div>
  </div>
</div>


这里每一个tab里面的导航和内容是一起的,我们称为合并模式吧,这种在组件化里面很常见,比如在react里面,一个tab组件,一般会写成这样

ReactDOM.render(
  <Tabs defaultActiveKey="1" onChange={callback}>
    <TabPane tab="Tab 1" key="1">Content of Tab Pane 1</TabPane>
    <TabPane tab="Tab 2" key="2">Content of Tab Pane 2</TabPane>
    <TabPane tab="Tab 3" key="3">Content of Tab Pane 3</TabPane>
  </Tabs>,
mountNode);


是不是很像?

相信用js只要是一名合格的前端都能轻易的实现吧,这里我们主要是研究如何用css来实现。


第一种布局(分离模式)


这里有两种思路


  1. 锚点实现 herf + :target
  2. css3 nth-child(n) 选择器

锚点实现主要是在a标签加上href属性,然后目标元素上添加相同的id,当点击a标签时,目标元素的:target就生效了

<style>
#item01:target{ background:red }
</style>
<a href="#item01">跳转</a>
<div id="item01">内容</div>


这种方式可以将导航和内容链接到一块,但是在浏览器中有一个很不友好的地方,就是当点击带有锚点的a链接的时候,浏览器会自动定位到目标位置,很影响体验,需要去掉这种效果估计还得借助js来实现,故不太推荐用这种方式


nth-child(n) 选择器,这种方式就比较传统了,不过导航切换部分还是用到label+input[type=radio],实现基本和js是同一个思路,甚至还不如js方便,因为你有多少个tab选项就得写多少个nth-child样式

.tab-nav input:nth-of-type(1):checked ~ .tab-content :nth-of-type(1),
.tab-nav input:nth-of-type(2):checked ~ .tab-content :nth-of-type(2),
.tab-nav input:nth-of-type(3):checked ~ .tab-content :nth-of-type(3),
...
{
  z-index:1
}


你大概会看到这样的样式,如果选项卡比较固定,基本是静态的,比较少,可以一一写出来,如果比较多,或者是js生成的,那么建议这一部分样式也通过js生成出来。

下面着重来实现第二种布局


第二种布局(合并模式)


如果是这样一种布局,那么导航和内容就可以通过相邻选择器+联系上了,重点是如何实现选项卡的样式,当然,我们也需要改一下html

<div class="tabs">
  <div class="tab-pane">
    <input type="radio" name="tab" id="tab01"/>
    <label class="tab-item" for="tab01">tab01</label>
    <div class="tab-content">111</div>
  </div>
  <div class="tab-pane">
    <input type="radio" name="tab" id="tab02"/>
    <label class="tab-item" for="tab02">tab02</label>
    <div class="tab-content">222</div>
  </div>
  <div class="tab-pane">
    <input type="radio" name="tab" id="tab03"/>
    <label class="tab-item" for="tab03">tab03</label>
    <div class="tab-content">333</div>
  </div>
</div>


然后我们通过样式美化一下

.tabs{
  position:relative;
  width:400px;
  height:300px;
}
.tab-pane{
  display:inline-block;
}
.tabs input[type='radio']{
  position:absolute;
  clip:rect(0,0,0,0)
}
.tab-item{
  display:block;
  height:34px;
  line-height:34px;
  cursor:pointer;
  padding:0 10px
}
.tab-content{
  position:absolute;
  border:1px solid #eee;
  padding:20px;
  left:0;
  top:36px;
  bottom:0;
  right:0;
  background:#fff;
}


然后加入交互,主要就是相邻选择器+:checked选择器,

.tabs input[type='radio']:checked+.tab-item{/**导航选中状态**/
  background:orangered;
  color:#fff
}
.tabs input[type='radio']:checked+.tab-item+.tab-content{/**当前内容切换**/
  z-index:1
}


我们这里只用了z-index:1就实现了隐藏显示,当然还可以实现更多的效果,比如淡入淡出等


下面是演示效果


https://codepen.io/xboxyan/pe...点击预览


当然,这种方式也有一定的不足,由于这里内容区域用到了绝对定位,所以整个tab容器就不能根据里层的内容来自适应,也需要给外层一个固定的高度,不然整个tab容器就只有顶部导航区域才占据空间,这明显就不合常理。


添加一点动画效果

/**给导航添加横条的缩放效果**/
.tab-item:after{
  position:absolute;
  content:'';
  height:3px;
  width:100%;
  background:orangered;
  left:0;
  bottom:2px;
  transition:.3s;
  transform:scaleX(0)
}
.tabs input[type='radio']:checked+.tab-item:after{
  transform:scaleX(1)
}
/**给内容区域添加一个淡入淡出的效果**/
.tab-content{
  position:absolute;
  background:#eee;
  padding:20px;
  left:0;
  top:36px;
  bottom:0;
  right:0;
  transition:.3s;
  opacity:0;
  transform:translateY(50px)
}
.tabs input[type='radio']:checked+.tab-item+.tab-content{
  z-index:1;
  opacity:1;
  transform:translateY(0)
}


https://codepen.io/xboxyan/pe...点击预览


小节


通过css我们也能实现导航效果,而且更容易复用,只需要复制html结构就行(当然这里肯定也是需要改一下nameid的)。这就有点类似组件的意思了,给你一个html结构,你不需要关系切换逻辑,只需要根据接口取到数据,然后塞到每个tab标签页里面去,事实上现在react实现的组件也一般都是这种思路,只需关注业务逻辑,但这些都是大工程,哪里有css直接来的快。


这就让我想到了刚进公司那会,每碰到一个tab,那就要取一个id,然后用jquery实现一遍tab切换逻辑,后来放聪明了,把tab封装成一个插件,碰到一个tab就调用一次插件...看着代码变少了,其实也没什么本质区别。


用css来实现的好处就是可以尽量大的把组件功能和业务逻辑分离开来,真正做一个UI组件该做的事,希望css越来越好。

相关文章
|
前端开发 JavaScript 开发者
利用 SplitingJS 配合 CSS 实现文字&quot;蠕动&quot;效果
利用 SplitingJS 配合 CSS 实现文字&quot;蠕动&quot;效果
377 2
|
前端开发 JavaScript
HTML+CSS+JAVASCRIPT实现——情人节表白情书
本文主要介绍如何使用HTML三件套来实现制作一封情人节表白情书,富含情谊与爱,打动女生的心灵
754 2
HTML+CSS+JAVASCRIPT实现——情人节表白情书
|
前端开发 容器
面试官:请使用 CSS 实现自适应正方形
面试官:请使用 CSS 实现自适应正方形
501 0
面试官:请使用 CSS 实现自适应正方形
|
4月前
|
前端开发
css 巧用 ::after 实现 tab 切换动效
css 巧用 ::after 实现 tab 切换动效
38 0
|
6月前
|
前端开发 JavaScript
jquery+css实现Tab栏切换的代码实例
jquery+css实现Tab栏切换的代码实例
106 0
|
JavaScript 前端开发
CSS进阶向--配合Vue动态样式实现“超炫酷”圆环菜单
CSS进阶向--配合Vue动态样式实现“超炫酷”圆环菜单
891 2
CSS进阶向--配合Vue动态样式实现“超炫酷”圆环菜单
|
前端开发 JavaScript
CSS进阶向--纯css实现流光边框(二)
CSS进阶向--纯css实现流光边框(二)
2301 1
CSS进阶向--纯css实现流光边框(二)
|
前端开发 JavaScript 程序员
CSS进阶向--纯css实现流光边框
CSS进阶向--纯css实现流光边框
1998 0
Html+Css实现——时间轴日志
本篇文章,主要讲解一下如何创建一个精美的时间轴日志页面,其中代码里具体的日志内容部分需要自行更改哦!
386 1
Html+Css实现——时间轴日志
|
前端开发 容器
我已经说了5种css居中实现的方式了,面试官竟然说还不够?
这是一篇关于居中对齐方式的总结 开篇之前,先问一下大家都知道几种居中的实现方式? 面试时答出来两三个就不错了,就怕面试官还让你继续说。今天就来总结一下这些居中的方式 使用flex布局设置居中。 使用flex 时也能通过给子项设置margin: auto实现居中。 使用绝对定位的方式实现水平垂直居中。 使用grid设置居中。 使用grid时还能通过给子项设置margin: auto实现居中。 使用tabel-cell实现垂直居中。 还有一种不常用的方法实现垂直居中。 最后还有一种奇葩的方法。容器设置position: relative。孩子设置 top、left、bottom、right都设
172 0
我已经说了5种css居中实现的方式了,面试官竟然说还不够?

热门文章

最新文章