前端学习(5): 基于 Grid 和 Flex 布局的纯CSS多Tab切换

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


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

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

前端学习(5): 基于 Grid 和 Flex 布局的纯CSS多Tab切换

我们要模仿的是最底部的 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-columns1fr;
  grid-template-rows1fr auto;
  margin10px auto;
  width220px;
  height260px;
  border-radius5px;
}

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

.container > .main {
  grid-area1 / 1;
}

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

前端学习(5): 基于 Grid 和 Flex 布局的纯CSS多Tab切换

实测效果如下:

前端学习(5): 基于 Grid 和 Flex 布局的纯CSS多Tab切换
Tab切换实测

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

怎么办?

巧设默认菜单

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

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

其设定方式如下:

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

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

前端学习(5): 基于 Grid 和 Flex 布局的纯CSS多Tab切换

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

前端学习(5): 基于 Grid 和 Flex 布局的纯CSS多Tab切换

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

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


怎么只显示一个菜单内容

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

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

所以我们才把 <div id=”a” class=”main”>微信</div> 放在了最后。

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

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


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

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

– END –


原文始发于微信公众号(背井):前端学习(5): 基于 Grid 和 Flex 布局的纯CSS多Tab切换

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/246768.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!