就像上图这样的动画效果
在导航栏里的时候,下划线跟随鼠标移动,鼠标移出导航栏时,下划线回到初始位置,同时要适应导航的宽度
为了适应导航的宽度,就不能给导航元素设置 margin,然后将导航元素的 clientWidth 设置给下划线
然后需要让下划线独立于导航之外,从而保证它的无缝滑动(其实也可以用伪类元素实现,不过效果不够好)
再根据左侧导航的宽度总和,计算出下划线左移的距离
一、基本结构
基于上面的思路,HTML 结构可以设计成这样:
并将下划线的 width 和 left 设置为动态 style,在鼠标滑动时实时修改
然后给 MainHeader 和 Underline 添加 CSS 样式:
.main { position: relative; width: fit-content; margin: 0 auto; text-align: center; } .nav-underline { position: absolute; bottom: 0; display: block; height: 2px; background-color: #000; transition: all .2s ease-out; }
二、移动下划线
因为需要实时修改下划线的宽度,所以需要监听 mouseenter 事件,获取当前元素
但如果导航元素 nav 还有子元素 (比如上面的 nav-title),直接用 event.target 就有问题
经过取舍,我决定获取 MainHeader 的 childNodes,然后根据 v-for 的 index 去查找对应的导航元素
在对应的事件处理函数里面,将导航元素的 clientWidth 设置为下划线的宽度
同时计算当前导航的左侧所有导航的宽度之和,作为下划线的左移距离
setCurrentNav (index) { // 鼠标移动到导航时,记录临时状态 this.currentNav = index this.currentNavStyle = this.getNavStyle(index) }, getNavStyle (index) { // 根据导航的 index 移动下划线 let childNodes = this.$refs.MainHeader.childNodes // 根据当前导航的宽度,设置下划线的宽度 let width = childNodes[index].clientWidth // 设置下划线的默认位置 let left = 0 if (index > 0) { // 计算左边导航的总宽度,设置为下划线的左移距离 for (let i = 0; i < index; i++) { left += childNodes[i].clientWidth } } return {width, left} }
最后在 computed 里面动态修改下划线样式
三、完善激活状态
上面实现了鼠标移动时候的下划线跟随效果
但对于点击导航后但激活状态 active 还没有做处理
在导航元素上添加 click 事件的处理函数,记录下激活元素的 index
setActiveNav (index) { // 点击导航时,设置激活样式 this.activeNav = index this.activeNavStyle = this.getNavStyle(index) }
当鼠标移出 MainHeader 的时候,下划线还得回到 active 的位置
上面已经对 navLineStyle() 做了兼容处理,所以只需要在鼠标移出的时候,清空 currentNavStyle 即可
handleLeaveMainHeader () { // 鼠标离开导航栏时,重置下划线状态 this.currentNavStyle = null }
四、纯CSS实现下划线跟随
参考链接:https://github.com/chokcoco/iCSS/issues/33
如果对于整个动画效果的要求不是特别高, 可以用伪类元素实现下划线跟随
所以 HTML 结构里面就不用将下划线独立出来
然后使用 after 画出下划线
.nav { position: relative; overflow: hidden; &::after { content: ''; position: absolute; bottom: 0; left: 100%; width: 0; height: 2px; background-color: #000; transition: all 0.3s ease-out; } }
这里设置了 width: 0; left: 100%; 这是为了让下划线默认从右向左出现,然后从左向右消失
然后在 hover 状态下,将对应的 after 设置为 width: 100%; left: 0;
最后使用 CSS 中的相邻元素选择器 ( + ) 选择相邻的 after,设置左移为 left: 0;
.nav { &:hover { &::after { width: 100%; left: 0; } & + .nav::after { left: 0; } } }
从而实现相邻下划线 after 能从左向右出现,动画连起来就像是下划线跟随鼠标滑动了
这种方式不够完美,但仅仅需要几行 CSS 就能实现,还是非常厉害的
来源:https://www.cnblogs.com/wisewrong/p/10371105.html