js+css制作导航栏下划线跟随动画,App+H5点击效果
这是使用Vue制作的一个下划线跟随效果,没有使用其他插件
2023.2.7更新
这个做法有很多缺陷,有其他更好的解决方案,已经更新在新文章里了,感兴趣的朋友可以去新文章里看↓
这是使用Vue制作的一个下划线跟随效果,没有使用其他插件
目录
这是最终效果↓
一开始从网上查其他人的做法,大部分都是使用下边框,或者伪元素+边框的方式去实现。
单纯只使用边框的话,边框的长度是根据选项内容的长度去变化的,这一点不是特别好,虽然可以在伪元素里写边框来解决,但是我觉得这么做有个弊端,就是边框线不能设置圆角,这样美感上会差一点点......
回归正题,我是这么实现的↓
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,只使用变化属性transform的translateX()可以实现一样的效果↓
<!-- 只使用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>
注意事项
- 导航栏 .nav-list 的flex样式,一定要使用 justify-content: space-around; 否则会导致后续计算下划线移动距离不准确
- 可以定义下划线的样式,也可以使用background-image属性制作渐变色下划线
- 如果导航栏选项文字数量(长度)不同,也会导致下划线移动不准确,最好统一选项文字数量(长度),或者各路大神自行解决
- 欢迎留言,不喜勿喷
更多推荐
所有评论(0)