2023.2.7更新

这个做法有很多缺陷,有其他更好的解决方案,已经更新在新文章里了,感兴趣的朋友可以去新文章里看↓

js+css制作导航栏下划线跟随动画,自适应元素尺寸变化,自定义下划线样式,Vue/Uniapp_千叶KE的博客-CSDN博客导航栏下划线跟随动画,自适应元素尺寸变化,自定义下划线样式https://blog.csdn.net/qq1219579255/article/details/128822806


这是使用Vue制作的一个下划线跟随效果,没有使用其他插件

目录

1. 制作一个初始的导航栏

2. 增加点击样式

3. 下划线移动

最终代码

注意事项


这是最终效果


一开始从网上查其他人的做法,大部分都是使用下边框,或者伪元素+边框的方式去实现。

单纯只使用边框的话,边框的长度是根据选项内容的长度去变化的,这一点不是特别好,虽然可以在伪元素里写边框来解决,但是我觉得这么做有个弊端,就是边框线不能设置圆角,这样美感上会差一点点......

回归正题,我是这么实现的↓


1. 制作一个初始的导航栏

<body>
    <div id="app">
      <div class="nav">
        <!-- 标题列表 -->
        <div class="nav-list">
          <div v-for="(item, index) in navList" :key="index">{{ item }}</div>
        </div>
        <!-- 下划线 -->
        <div class="nav-line"></div>
      </div>
    </div>
</body>
<script>
    var vm = new Vue({
      el: "#app",
      data: {
        navList: ["首页", "头条", "特惠", "财经", "动漫"],
      },
    });
</script>
<style>
    * {
      box-sizing: border-box;
      padding: 0;
      margin: 0;
    }

    .nav {
      position: relative;
    }

    .nav-list {
      width: 100%;
      height: 50px;
      display: flex;
      justify-content: space-around;
      align-items: center;
    }

    .nav-line {
      width: 18px;
      height: 4px;
      border-radius: 2px;
      background-color: red;
      position: absolute;
      bottom: 0;
    }
</style>

以上呈现出来的效果是这样的


 2. 增加点击样式

首先我们要给导航里的每个选项增加点击事件,再点击时使点击项变色

  • HTML部分添加事件与动态class
<div class="nav-list">
    <div v-for="(item, index) in navList" :key="index" @click="click(index)" :class="{ active : index==current }">{{ item }}</div>
</div>
  •  Vue实例中添加变量与方法
data: {
        navList: ["首页", "头条", "特惠", "财经", "动漫"],
        current: 0,
},
methods: {
        // 点击时执行
        click(index) {
          this.current = index;
          this.lineMove();
        },
        // 计算下划线应该移动的距离
        lineMove() {
          
        },
},
  •  CSS部分增加样式
.active {
      color: red;
      font-weight: bold;
}

然后我们会得到这样的效果


完成前两步之后字体颜色已经改变了,接下来要让下划线跟着一起动起来

3. 下划线移动

  • HTML部分为下划线添加动态style

因为在之前已经为下划线添加了绝对定位,所以这里可以使用left属性进行位移

<div class="nav-line" :style="{left:X+'px',transform : 'translateX(-50%)'}"></div>

当然也可以不使用left,只使用变化属性transformtranslateX()可以实现一样的效果↓

<!-- 只使用transform的写法 -->
<div class="nav-line" :style="{transform : `translateX(${X}px) translateX(-50%)`}"></div>

注意translateX()一定要使用引号 ' ' 或者模板字符串 ` ` 包裹起来,不然会报错,translateX(-50%)是让下划线向左移动自身的50%以保证对齐,这点大家应该都明白

  • Vue实例中新增变量 X 与方法 lineMove
data: {
        navList: ["首页", "头条", "特惠", "财经", "动漫"],
        X: 0,
        current: 0,
},
methods: {
        // 点击时执行
        click(index) {
          this.current = index;
          this.lineMove();
        },
        // 计算下划线应该移动的距离
        lineMove() {
          // 导航栏的宽度,因为是100%所以就是屏幕宽度
          let width = document.body.clientWidth;
          // 每个选项栏的宽度 = 导航栏宽度/选项个数
          let divWidth = width / this.navList.length;
          // 半个选项栏宽度
          let halfDivWidth = divWidth / 2;
          // 下划线移动的距离 = 半个选项栏宽度 + (单个选项栏宽度*当前index)
          this.X = halfDivWidth + divWidth * this.current;
        },
 }, 

此处的 let width = .nav-list的宽度,因为我们之前在css中定义了.nav-list的宽度为100% ,所以我在示例中就去获取了当前的屏幕的宽度。

  • CSS为下划线增加过渡效果
.nav-line {
      width: 18px;
      height: 4px;
      border-radius: 2px;
      background-color: red;
      position: absolute;
      bottom: 0;
      transition: 0.3s all;
    }

得到效果

 做到这里可以看到效果已经实现了,但是仍然有点小问题 —— 页面初始化时下划线位置不对,在屏幕最左侧而且有一半溢出了屏幕,原因也很明显,我们给变量X定的初始值是0。

解决问题:在生命周期created中执行一次lineMove方法

created() {
        // 避免页面初始化会有显示问题,初始加载时就执行一次该方法
        this.lineMove();
      },

注意:这里建议在created周期中执行,而不是在mounted周期中,因为mounted是在页面初次加载完成之后执行,所以在mounted里执行我们会在一开始看到下划线短暂的停留在屏幕左侧。

得到最终效果↓


最终代码

  <body>
    <div id="app">
      <div class="nav">
        <!-- 标题列表 -->
        <div class="nav-list">
          <div v-for="(item, index) in navList" :key="index" @click="click(index)" :class="{ active : index==current }">{{ item }}</div>
        </div>
        <!-- 下划线 -->
        <div class="nav-line" :style="{left:X+'px',transform : 'translateX(-50%)'}"></div>
        <!-- <div class="nav-line" :style="{transform : `translateX(${X}px) translateX(-50%)`}"></div> -->
      </div>
    </div>
  </body>
  <script>
    var vm = new Vue({
      el: "#app",
      data: {
        navList: ["首页", "头条", "特惠", "财经", "动漫"],
        X: 0,
        current: 0,
      },
      methods: {
        // 点击时执行
        click(index) {
          this.current = index;
          this.lineMove();
        },
        // 计算下划线应该移动的距离
        lineMove() {
          // 导航栏的宽度,因为是100%所以就是屏幕宽度
          let width = document.body.clientWidth;
          // 每个选项栏的宽度 = 导航栏宽度/选项个数
          let divWidth = width / this.navList.length;
          // 半个选项栏宽度
          let halfDivWidth = divWidth / 2;
          // 下划线移动的距离 = 半个选项栏宽度 + (单个选项栏宽度*当前index)
          this.X = halfDivWidth + divWidth * this.current;
        },
      },
      created() {
        // 避免页面初始化会有显示问题,初始加载时就执行一次该方法
        this.lineMove();
      },
    });
  </script>
  <style>
    * {
      box-sizing: border-box;
      padding: 0;
      margin: 0;
    }

    .nav {
      position: relative;
    }

    .nav-list {
      width: 100%;
      height: 50px;
      display: flex;
      justify-content: space-around;
      align-items: center;
    }

    .active {
      color: red;
      font-weight: bold;
    }

    .nav-line {
      width: 18px;
      height: 4px;
      border-radius: 2px;
      background-color: red;
      position: absolute;
      bottom: 0;
      transition: 0.3s all;
    }
  </style>

注意事项

  1. 导航栏 .nav-list 的flex样式,一定要使用 justify-content: space-around; 否则会导致后续计算下划线移动距离不准确
  2. 可以定义下划线的样式,也可以使用background-image属性制作渐变色下划线
  3. 如果导航栏选项文字数量(长度)不同,也会导致下划线移动不准确,最好统一选项文字数量(长度),或者各路大神自行解决
  4. 欢迎留言,不喜勿喷
Logo

前往低代码交流专区

更多推荐