善用 CSS 伪类, 不用 JS 也能做出选项卡功能
先看看 Demo:
讲到选项卡 (Tabs) 功能时, 大多会想到用 JavaScript 去做, 像知名的前端框架: Bootstrap 所提供的 Tab 元件, 就是用 jQuery 实现的(其实网络上有很多用 jQuery 开发的 Tab); 但其实不用 jQuery 或 JavaScript 技术, 就能实现高效能且易维护的 Tabs 元件, 让我们来看看是怎么办到的:
规划 html 结构
通常我们会用列表元素来制作选项卡的界面, 每个 < li > 代表用来包含一组选项卡与其对应的内容块. 接下来加入选项卡, 选项卡必须使用 < label > 元素才能实作我们要的功能, 原因待会会讲, 是这篇文章的核心技巧之一.
内容块则是 < div > 元素. 再来我们为每个 < label > 前面加上表单元素 Radio button, 结果如下:
- <ul class="tabs">
- <li>
- <input type="radio" name="tabs">
- <label class="tab">页面 A</label>
- <div class="section">内容 A</div>
- </li>
- <li>
- <input type="radio" name="tabs">
- <label class="tab">页面 B</label>
- <div class="section">内容 B</div>
- </li>
- <li>
- <input type="radio" name="tabs">
- <label class="tab">页面 C</label>
- <div class="section">内容 C</div>
- </li>
- </ul>
为什么使用 Label 与 Radio button?
这篇文章的主要技巧也就是要靠这两种元素的特性, 因为我们要 "借用"Radio button 的单选特性, 决定哪个 Tab 是 Active, 同时确保其他 Tab 是未选中的状态.
Radio button 默认的样式是非常丑陋的, 而且我们能改动的样式也是有限的, 所以不建议直接把它设计成 Tab, 所以我们使用 < label > 来担任触发的角色, 也比较容易改变样式, 再藉由 Label 的 For 属性去触发对应 id 的 Radio button.
所以我们为 Radio button 加上 id, 然后将 Label 的 for 属性指向对应的 id:
- <ul class="tabs">
- <li>
- <input type="radio" name="tabs" id="tabA">
- <label class="tab" for="tabA">页面 A</label>
- <div class="section">内容 A</div>
- </li>
- <li>
- <input type="radio" name="tabs" id="tabB">
- <label class="tab" for="tabB">页面 B</label>
- <div class="section">内容 B</div>
- </li>
- <li>
- <input type="radio" name="tabs" id="tabC">
- <label class="tab" for="tabC">页面 C</label>
- <div class="section">内容 C</div>
- </li>
- </ul>
这样就完成我们的 HTML 结构了, 再来要写点 CSS, 让功能得以运作起来.
写点 CSS
我们先让 < li > 并排 (display:inline-block). 再来为 < label > 和内容块 < div class="section"> 设计外观.
特别注意内容块用绝对定位让每次显示的内容都在同样的位置, 之后我们再控制层叠等级 (z-index) 和透明度 (opacity) 来实现显示 / 隐藏.
- li { display: inline-block; }
- input[type="radio"] {
- position: absolute;
- outline: none;
- ...
- }
- .tab {
- ...
- }
- .section {
- position: absolute;
- top: 50px; // 取决于你的 Label 高度
- left: 0;
- ...
- }
咦? 还是不能动? 因为我们还需要运用 CSS 的两个重要技巧: 伪类 (Pseudo-class) 和通用兄弟元素选择器(Sibling Combinator), 才能让选项卡与内容块做切换.
加入 CSS 伪类与通用兄弟元素选择器
我们为 Radio button 加上伪类: checked, 表示当这个 Radio button 被选中时 (等于对应的标签被选中使) 才会呈现的样式.
- input[type="radio"]:checked {
- ...
- }
然后要做切换动作的是选项卡和内容块, 由于它们与 Radio button 属同一层父元素, 所以我们这里要用到通用兄弟元素选择器~ 来做, 通用兄弟元素选择器有两种:
相邻兄弟选择器 (Adjacent Sibling Combinator) 是用来选择互为兄弟元素的相邻的元素.
通用兄弟元素选择器 (General Sibling Combinator) 则是用来选择互为兄弟元素的所有匹配的元素.
我们使用通用兄弟元素选择器即可:
- input[type="radio"]:checked ~ .tab { // 这里也可以使用相邻兄弟选择器来做
- ...
- }
- input[type="radio"]:checked ~ .section {
- ...
- z-index: 2;
- }
注意内容内存块 (.section) 要加上 z-index 属性才能覆盖其它选项卡的内容块, 最后我们再将 Radio button 设为透明或使用定位的技巧让它消失在页面上, 前面没有先提这点的原因, 是因为可以让你在点选选项卡时, 观察 Radio button 的选中状态变化, 同时也方便测试, 确认选项卡对应的 Radio button 有正确被触发.
这样就大功告成啦!
自己是一个 6 年的前端工程师, 希望本文对你有帮助!
这里推荐一下我的前端学习交流扣 qun:731771211 , 里面都是学习前端的, 如果你想制作酷炫的网页, 想学习编程. 自己整理了一份 2019 最全面前端学习资料, 从最基础的 HTML+CSS+JS[炫酷特效, 游戏, 插件封装, 设计模式] 到移动端 HTML5 的项目实战的学习资料都有整理, 送给每一位前端小伙伴, 每天分享技术
点击: 加入
整理
大略整理一下重点与需要注意的地方:
Radio button 的单选特性是基于同样的 name 属性, 所以 name 一定要设, 而且要一样; 反之, 你可以设置多组 name 去实现多组的选项卡组件, 而且各自是独立运作, 不会互相影响.
Radio button 的 id 和 Label 的 for 是必要的属性.
内容块的定位要避免覆盖到选项卡.
注意 HTML 的结构是否正确, CSS 选择器的使用是否正确(选项卡和内容块有没有在同一层).
注意 z-index 的设置是否正确.
本篇文章的技术给予选项卡 UI 另一种开发的选择, Radio button 的特性还有很多应用可以做(如 Switcher), 只要善用 HTML 表单元素与 CSS 的一些技巧, 也能玩出很多有趣的功能, 甚至替代 JavaScript 的部份工作
来源: http://www.jianshu.com/p/87787ada1c46