css+js:实现tab切换线条跟随效果

目录

实现效果

使用css和js实现一个tab切换的效果

原理解析

如上图

  • 红色框框代表盒子,总宽度记作 totalWidth
  • 绿色框框代表每一项,宽度记作itemWidth
  • 深蓝色框框代表的是下划线,宽度记作activeWitdh

那么我们可以得到线的左边距是每一项的左边距加上一个值

这个值是每一项的宽度减去线的宽度的结果再除以二

js 复制代码
// index是当前点击的item索引,从0开始
itemWidth * index + (itemWidth - activeWitdh) / 2

代码实现

html 复制代码
<div id="app">
  <div class="tabs_wrap">
    <div
      v-for="(item, index) in tabsList"
      :key="item.value"
      :class="['item','item-' + (index+1)]"
      @click="changeIndex(index)"
    >
      {{ item.label || ""}}
    </div>
    <div class="active" :style="{left: left + 'px'}"></div>
  </div>
</div>
css 复制代码
.tabs_wrap {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-around;
  font-size: 32px;
  color: #333;
  font-weight: bold;
  height: 88px;
  line-height: 88px;
  border: 4px solid skyblue;
}

.item {
  cursor: pointer;
  border: 1px solid pink;
  flex: 1;
  text-align: center;
}

.active {
  position: absolute;
  left: 0;
  bottom: 0;
  width: 50px;
  height: 8px;
  background-color: #2979ff;
  border-radius: 50px;
  transition: left 0.3s ease;
}
html 复制代码
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>

<script>
  const { createApp } = Vue;

  const app = {
    data() {
      return {
        currentIndex: 0,
        left: 0,
        tabsList: [
          {
            label: "推荐",
            value: "1",
          },
          {
            label: "热点",
            value: "2",
          },
          {
            label: "八卦",
            value: "3",
          },
          {
            label: "娱乐",
            value: "4",
          },
        ],
      };
    },

    methods: {
      initPostion(index) {
        let currentItem = document.querySelector(".item-" + (index + 1));
        let activeItem = document.querySelector(".active");
        console.log(currentItem.offsetWidth);
        console.log(activeItem.offsetWidth);

        // 计算下划线位置
        this.left =
          currentItem.offsetWidth * index +
          (currentItem.offsetWidth - activeItem.offsetWidth) / 2;
        console.log(this.left);
      },

      changeIndex(index) {
        if (this.currentIndex === index) return;

        this.currentIndex = index;
        this.initPostion(index);
      },
    },

    mounted() {
      this.initPostion(0);
    },
  };

  createApp(app).mount("#app");
</script>

在线演示:https://mouday.github.io/front-end-demo/tabs/tabs.html

参考文章

  1. uniapp如何实现tab切换线条跟随效果
相关推荐
梦想很大很大11 小时前
从运行事实到回归证据:Workrun 的 Telemetry 与 Evaluation 实践
前端·人工智能·后端
计算机魔术师11 小时前
Meta Muse agent 接入 Shopify 的 Shop Pay 实现代理式购物
前端
沙蒿同学11 小时前
我用 Go 搭了一条 AI Agent 流水线:从 1 张商品图到一整套淘宝详情页
前端·javascript·后端
甜到心里的蛋糕12 小时前
加解密技术详解:纯前端如何实现 AES / SM4 / RSA / 国密 SM2
前端·密码学
拖孩12 小时前
代码我能全交给 AI,流量主这 500 个访客它一个都替不了我
前端·后端·微信小程序
2601_9638702112 小时前
基于SSM的特产代购系统
java·前端
paopaokaka_luck12 小时前
智慧社区综合服务小程序(人脸识别、AI问答、Echarts图形化分析)
前端·javascript·spring boot·spring·数据分析·echarts
烈风逍遥13 小时前
第七篇:提示词模板管理与 Agent 提示词编排
前端·人工智能·后端
Amos_Web13 小时前
Rspack 源码解析(十二):JavaScript Chunk 是如何被渲染出来的
前端·rust·源码
前端探险家Rick13 小时前
React Native 二级弹出面板 + 键盘适配:从踩坑到正确方案
前端