三分钟,纯 CSS 实现一个 tabs 组件

开发
glider​的样式定义了滑块的大小、位置和颜色,设置为absolute以便在容器内自由移动,transition使其移动平滑。

Hello,大家好,我是 Sunday。

tabs 组件是在日常开发中的常见组件,很多同学表示:组件库的 tabs 不好看,自己实现又不知道怎么去做。

所以说,今天,咱们就花上几分钟的时间,通过纯 css 的方式来实现一个 tabs 组件,以帮助大家完成自定义 tabs 组件的逻辑。

最终效果图最终效果图

html 部分

先上代码:

<div class="container">
  <div class="tabs">
    <input type="radio" id="radio-1" name="tabs" checked="" />
    <label class="tab" for="radio-1">
      首页
      <span class="notification">2</span>
    </label>
    <input type="radio" id="radio-2" name="tabs" />
    <label class="tab" for="radio-2">分类</label>
    <input type="radio" id="radio-3" name="tabs" />
    <label class="tab" for="radio-3">我的</label>
    <span class="glider"></span>
  </div>
</div>

这里需要 注意:在 html 部分需要设计成 input + label 的形式,而不能使用 div 的方案。

核心原因有两点:

  1. input[type='radio'] 元素天生就具有 互斥性,即只能选中一个。这使得在实现多选一的标签页功能时非常简便和自然,无需手动管理状态。
  2. 当选择某个标签页时,其对应的 radio 按钮会被选中,而 CSS 可以通过 :checked 伪类来捕捉这一状态的变化,从而触发样式变化,比如滑块的移动、文本颜色的变化等。

整个 HTML 结构设计逻辑如下:

  • container:最外层容器,用于包裹整个标签页组件。
  • tabs:用于包含标签页的所有内容,包括input、label和glider滑块。
  • input[type='radio']:作为标签页的控制器,决定哪个标签页被选中。每个标签页对应一个radio按钮,三个input元素的id和label元素的for属性配对,使得点击label可以选择对应的radio按钮。
  • label.tab:每个标签页的实际显示部分,包括文字和可选的通知标记notification。
  • glider:滑块,用于在标签页切换时移动,表示当前选择的标签页。

CSS样式

body {
    padding: 300px;
}

.tabs {
    width: 152px;
    display: flex;
    position: relative;
    background-color: #fff;
    box-shadow: 0 0 1px 0 rgba(24, 94, 224, 0.15), 0 6px 12px 0 rgba(24, 94, 224, 0.15);
    padding: 12px;
    border-radius: 99px;
}
  • body:在body中添加了padding,使页面内容离顶部和边界有一定的距离,便于演示。
  • tabs:设置了tabs容器的宽度(152px),使用flex布局,子元素排列在一行。容器具有一定的阴影效果和圆角,使其更具层次感。
.tabs * {
    z-index: 2;
}
  • 将tabs内部的所有元素的z-index设置为2,确保这些元素位于滑块(glider)之上。
.container input[type='radio'] {
    display: none;
}
  • 隐藏radio按钮,只保留它们的功能,不显示在页面上。
.tab {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 30px;
    width: 50px;
    font-size: 14px;
    color: black;
    font-weight: 500;
    border-radius: 99px;
    cursor: pointer;
    transition: color 0.15s ease-in;
}
  • 每个标签页label.tab设置了固定的大小,字体样式和颜色。使用flex布局使文本居中,边角圆滑,鼠标悬停时呈现为点击手势。使用transition实现颜色过渡效果。
.notification {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 14px;
    height: 14px;
    position: absolute;
    top: 10px;
    left: 30%;
    font-size: 10px;
    margin-left: 10px;
    border-radius: 50%;
    background-color: #e6eef9;
    transition: 0.15s ease-in;
}
  • notification是标签页上的小圆点,用于显示通知数量。设置了大小、位置、字体大小和颜色。transition使背景色和位置的变化更为平滑。
.container input[type='radio']:checked + label {
    color: #185ee0;
}

.container input[type='radio']:checked + label > .notification {
    background-color: #185ee0;
    color: #fff;
    margin: 0px;
}
  • 当radio按钮被选中时,相应的label颜色变为蓝色,通知标记的背景色和文本颜色也会改变。
.container input[id='radio-1']:checked ~ .glider {
    transform: translateX(0);
}

.container input[id='radio-2']:checked ~ .glider {
    transform: translateX(100%);
}

.container input[id='radio-3']:checked ~ .glider {
    transform: translateX(200%);
}
  • 通过CSS选择器,当某个radio按钮被选中时,glider滑块将根据不同的radio按钮移动相应的距离,translateX是基于父容器的宽度(这里是152px)。
.glider {
    position: absolute;
    display: flex;
    height: 30px;
    width: 50px;
    background-color: #e6eef9;
    z-index: 1;
    border-radius: 99px;
    transition: 0.25s ease-out;
}
  • glider的样式定义了滑块的大小、位置和颜色,设置为absolute以便在容器内自由移动,transition使其移动平滑。
责任编辑:武晓燕 来源: 程序员Sunday
相关推荐

2024-05-16 11:13:16

Helm工具release

2009-11-09 12:55:43

WCF事务

2023-12-27 08:15:47

Java虚拟线程

2024-01-16 07:46:14

FutureTask接口用法

2022-02-17 09:24:11

TypeScript编程语言javaScrip

2021-04-20 13:59:37

云计算

2024-08-30 08:50:00

2022-01-06 18:20:20

Scarlet AndroidWebSocket

2024-06-06 08:50:43

2020-06-30 10:45:28

Web开发工具

2013-06-28 14:30:26

棱镜计划棱镜棱镜监控项目

2021-12-17 07:47:37

IT风险框架

2009-11-05 16:04:19

Oracle用户表

2020-06-29 07:42:20

边缘计算云计算技术

2024-10-15 09:18:30

2024-07-05 09:31:37

2024-01-12 07:38:38

AQS原理JUC

2023-12-04 18:13:03

GPU编程

2021-02-03 14:31:53

人工智能人脸识别

2024-07-29 12:21:12

点赞
收藏

51CTO技术栈公众号