flex将元素放在最后_前端学习(5): 基于 Grid 和 Flex 布局的纯CSS多Tab切换

准备深入学习一下前端并计划每周至少写一篇关于前端的文章。这是第五篇啦。


最近迷上了 GridFlex 布局,今天尝试一下用它们配合 :target 伪类选择器,模仿手机 app 上见的 Bottom navigation bar

比如微信某一屏是这样的:

e363e756e411ca5cbffadcfc2f268c4f.png

我们要模仿的是最底部的 tab菜单 及切换效果(点 tab 切换屏幕)。

先谈谈布局

简化后,可以认为整个屏幕是一个盒子,最下面是 tab菜单栏,其余是 主体内容

HTML 结构如下:

<div class="container">
  <div id="b" class="main">通讯录div>
  <div id="c" class="main">发现div>
  <div id="d" class="main">我div>
  <div id="a" class="main">微信div>

  <div class="tabs">
    <a class="tab" href="#a">微信a>
    <a class="tab" href="#b">通讯录a>
    <a class="tab" href="#c">发现a>
    <a class="tab" href="#d">我a>
  div>
div>

从这个结构解释我们的意图:

  1. 默认4条 .main(主体内容) 都不可见:
.container > .main {
  visibility: hidden;
}
  1. 当用户点击 .tab 菜单时,让相应id的 .main 显示出来( id 由菜单的 href 属性指定 ):
.container > .main:target {
  visibility: visible;
}
  1. 对于底部4个 tab 菜单,我们希望它均匀分布,最好的解决方式自然是 flex + space-around
.container > .tabs {
  display: flex;
  justify-content: space-around;
}
  1. 最后,也是用到 Grid 布局的地方。因为整个盒子由 .main 主体内容 和 底部 .tabs 菜单组成,所以,盒子这个 Grid 有2行1列。为了模仿手机屏,我们还给它设置了宽高:
.container {
  display: grid;
  grid-template-columns: 1fr;
  grid-template-rows: 1fr auto;
  margin: 10px auto;
  width: 220px;
  height: 260px;
  border-radius: 5px;
}

这样还不够,还需要将4个 .main 全落在第一行第一列中:

.container > .main {
  grid-area: 1 / 1;
}

此时,用 Chrome 审查元素,将看到如下效果:

0b3572285db0719b6fde37e7340a788b.png

实测效果如下:

82867fde72cb15d4100e9b380a67b721.gif
Tab切换实测

基本满足要求了,但还有一个缺点:初次打开页面时,如果没点过任何菜单,则主体区域是白屏。原因很简单,刚开始时我们将所有 .main 都设为了不可见了(见上面标号为1的说明)。

怎么办?

巧设默认菜单

我们要做的是,当没有点击过任何 tab 菜单时,打开一个默认菜单

如果你仔细看过文章开头的 HTML 结构,.main 元素和 .tab 元素的顺序并不相同 —— 在 .main 中,我把 微信 放在了最后。这也是我要选的默认菜单。

其设定方式如下:

  1. 在默认4个 .main 不可见的基础上,将第4个 .main(即 微信) 设为可见:
.container > .main:nth-child(4) {
  visibility: visible;
}

这样,没点过菜单也能看到默认内容了:

d59fc7ff3e8a2c8a025a5af30ef97d96.png

但。。,这样会触发另一个问题,当点击其它菜单时,主体内容区会出现重叠:

d845979974be1a9c8cdc693950151c59.png

原因也很明显:其它菜单的内容和微信菜单的内容此时都处于可见状态,在同一区域显示,自然会重叠

读者朋友可以先想想或试试自己怎么解决这个问题,再接着往下读。


怎么只显示一个菜单内容

这个办法很讨巧,要2步才能完成:

  1. 在 HTML 结构上,默认显示的内容要放在其它内容的后面:

所以我们才把

微信
放在了最后。
  1. 当某个菜单被点击后,该菜单内容后的其它菜单内容设置为不可见:
.container > .main:target ~ .main {
  visibility: hidden;
}

利用兄弟选择器 ~ 可以选择某元素后面的兄弟元素,当我们点击任一菜单时,都将该菜单内容后面的内容设为不可见,而 微信菜单内容 一直都是在后面,所以它就永远不会和其它内容同时出现了。


可见,一个常见的 Tab 菜单,涉及的技术点也不能说少!

点击【阅读原文】可体验实际的 tab 切换效果。

- END -
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值