当前位置: 首页 > Web前端 > CSS

使用纯css实现tab切换

时间:2023-03-30 22:29:38 CSS

今天我们使用css实现一个常见的tab切换效果查看原文为了更好的排版效果先看效果https://codepen.io/xboxyan/pe...什么是前言简单的效果可以用css实现。目前css能做的交互都是mousepassing/leaving:hovermouseclick::cheked,那么上面的交互是不是都可以用css来实现呢?显然不是,css实现依赖于html结构,因为css的选择器是有限的,有子选择器,没有父选择器,有后选择器,没有前选择器,所以局限性非常大。因此,我们在考虑是否可以使用CSS来实现的时候,还要考虑HTML的结构,是否可以构造出满足CSS已有选择器的HTML布局。让我们从html结构开始。一般遇到tab类型的组件一般会有如下htmltab01

tab02
tab03
111
222
333
大致就是这样的布局,姑且称之为分离模式吧,足够灵活,也就是导航部分和内容结构是分开,需要的任何动画效果都可以单独实现。还有另一种布局,大概是这样的>111tab01111tab01111/div>在这里,每个选项卡中的导航和内容都放在一起。我们称之为合并模式。这在组件化中很常见。比如在react中,一个tab组件一般写成ReactDOM.render(ContentofTabPane1选项卡窗格2的内容选项卡窗格3的内容,mountNode);相似吗?相信只要是合格的前端,用js都能轻松实现。这里主要研究如何使用css实现第一个布局(分离模式)。这里有两种思考锚点实现的方式herf+:targetcss3nth-child(n)选择器锚点实现主要是给a标签加上href属性,然后给目标元素加上相同的id。当点击a标签时,目标元素的:target会生效="item01">content这种方式可以把导航和内容链接在一起,但是有一个对浏览器很不友好的地方,就是点击带有锚点的a链接时,浏览器会自动定位目标位置,这会影响体验。如果需要去掉这个效果,可能要用js来实现,不推荐使用nth-child(n)选择器这个方法,这个方法比较传统,但是导航切换部分还是用label+input[type=radio],实现方式基本和js一样一种思路甚至没有js方便,因为你有多少tab选项就得写多少nth-child样式。tab-navinput:nth-of-type(1):checked~.tab-content:nth-of-type(1),.tab-nav输入:nth-of-type(2):checked~.tab-content:nth-of-type(2),.tab-navinput:nth-of-type(3):checked~.tab-content:nth-of-type(3),...{z-index:1}你可能会看到这个style,如果tab比较固定,基本是静态的,比较少,可以一个个写出来,如果比较多,或者是js生成的,那么建议这部分的style也生成通过js下面重点实现第二种布局。第二种布局(合并模式)如果是这样的布局,那么导航和内容可以通过相邻的选择器+连接起来。重点是如何实现选项卡的样式。当然,我们还需要更改htmltab01111tab02222tab03333然后我们通过style.tabs美化一下{position:relative;宽度:400px;height:300px;}.tab-pane{display:inline-block;}.tabsinput[type='radio']{position:absolute;clip:rect(0,0,0,0)}.tab-item{display:block;高度:34px;行高:34px;光标:指针;padding:010px}.tab-content{position:absolute;边框:1px实心#eee;填充:20px;左:0;顶部:36px;底部:0;右:0;background:#fff;}然后添加交互,主要是相邻选择器+和:checked选择器,.tabsinput[type='radio']:checked+.tab-item{/**导航选中状态**/background:orangered;color:#fff}.tabsinput[type='radio']:checked+.tab-item+.tab-content{/**当前内容切换**/z-index:1}这里只有z-index:1用于实现隐藏显示。当然还可以实现更多的效果,比如淡入淡出。下面是演示效果https://codepen.io/xboxyan/pe...当然,这种方式也存在一定的不足。由于这里contentarea使用了绝对定位,整个tab容器无法根据内层的内容进行自适应,需要给外层一个固定的高度,否则整个tab容器只会占据最上面的空间导航区,明显不合理添加一点动画效果/**导航添加横条缩放效果**/.tab-item:after{position:absolute;内容:'';高度:3px;宽度:100%;背景:橙色;左:0;底部:2px;过渡:.3s;transform:scaleX(0)}.tabsinput[type='radio']:checked+.tab-item:after{transform:scaleX(1)}/**给内容区域添加淡入淡出效果**/.tab-内容{位置:绝对;背景:#eee;填充:20px;左:0;顶部:36px;底部:0;右:0;过渡:.3s;不透明度:0;transform:translateY(50px)}.tabsinput[type='radio']:checked+.tab-item+.tab-content{z-index:1;不透明度:1;transform:translateY(0)}https://codepen.io/xboxyan/pe...section我们也可以通过css实现导航效果,而且更容易复用,复制html结构即可(当然我们也必须在此处更改名称和ID)。这有点类似于组件。给定一个html结构,不需要关系切换逻辑,只需要根据接口获取数据,然后塞到各个标签页中即可。其实react实现的组件也是一般的都是这种思路,只关注业务逻辑,但是这些都是大项目,css可以直接来。这让我想起了刚进公司的时候,每次遇到tab都要取一个id,然后用jquery实现tab的切换逻辑。后来灵机一动,把tab封装成了一个插件,遇到tab调用一次插件就可以了。。。看到代码减少了,其实没有本质区别。使用css的好处是可以尽可能的分离组件功能和业务逻辑,真正做到一个UI组件该做的事情。希望css越来越好