右侧导航按钮多元素同时hover时左移问题排查求助
右侧导航栏快速hover时元素偏移问题排查与解决
我在页面右侧实现了导航栏,鼠标hover按钮时会触发放大动画,但快速连续hover多个按钮时,元素会向左偏移。怀疑是频繁触发mouseover/mouseout事件导致.buttons容器移位,相关代码如下:
原代码
JavaScript
// 按钮宽度放大逻辑 document.querySelectorAll(".nav-button").forEach(elem => elem.addEventListener("mouseover", () => { elem.querySelector(".nav-hover").style.width = "300%"; })); document.querySelectorAll(".nav-button").forEach(elem => elem.addEventListener("mouseout", () => { elem.querySelector(".nav-hover").style.width = ""; }));
CSS
.navigation { z-index: 10; position: absolute; right: 0px; } .navigation .buttons { position: absolute; top: 50%; transform: translate(-50%, -50%) !important; } .button-el { height: 65px; margin-bottom: 30px; } .button-el i { color: var(--text-color); font-size: 28px; position: relative; float: right; margin-top: 15px; margin-right: 15px; } .nav-hover { z-index: -1; transition: width .5s ease-out, opacity 0s, all 1s; position: relative; width: 65px; height: 65px; border-radius: 500px; float: right; background-color: var(--dark1); border: var(--accent1) 3px solid; }
HTML
<div class="buttons"> <div class="nav-button button-el home"> <div class="active"></div> <div class="nav-hover"> <i class="fa-solid fa-house"></i> </div> </div> <div class="nav-button button-el home"> <div class="active"></div> <div class="nav-hover"> <i class="fa-solid fa-user-large"></i> </div> </div> <div class="nav-button button-el home"> <div class="active"></div> <div class="nav-hover"> <i class="fa-solid fa-house"></i> </div> </div> </div>
问题原因
- 容器定位依赖自身宽度:
.buttons使用transform: translate(-50%, -50%)实现垂直居中,这里的-50%是基于容器自身宽度计算的。当.nav-hover宽度变为300%时,会撑大父元素.nav-button,进而导致.buttons容器的整体宽度变化,translate(-50%,...)的偏移值会跟着改变,快速hover时容器宽度反复波动,就出现了向左偏移的问题。 - 事件频繁触发加剧问题:快速移动鼠标时,
mouseover和mouseout会高频触发,导致.nav-hover的宽度频繁切换,进一步放大了容器宽度的波动。
修复方案
方案1:固定容器宽度+CSS hover替代JS事件
给.buttons设置固定宽度,避免按钮宽度变化影响容器;同时用CSS:hover替代JS事件,减少事件触发的问题:
修改后的CSS:
.navigation { z-index: 10; position: absolute; right: 0px; } .navigation .buttons { position: absolute; top: 50%; transform: translate(-50%, -50%) !important; width: 65px; /* 固定容器宽度,与按钮默认宽度一致 */ } .button-el { height: 65px; margin-bottom: 30px; position: relative; /* 作为子元素绝对定位的参考 */ } .button-el i { color: var(--text-color); font-size: 28px; position: relative; float: right; margin-top: 15px; margin-right: 15px; z-index: 2; /* 确保图标在hover层上方 */ } .nav-hover { z-index: 1; transition: width .5s ease-out; position: absolute; /* 改为绝对定位,不占据文档流宽度 */ right: 0; /* 固定在右侧 */ width: 65px; height: 65px; border-radius: 500px; background-color: var(--dark1); border: var(--accent1) 3px solid; } /* 用CSS hover实现宽度变化,替代JS事件 */ .nav-button:hover .nav-hover { width: 300%; }
方案2:移除JS事件,仅用CSS处理
直接删除原有的JavaScript代码,因为CSS:hover已经可以实现宽度变化的效果,同时避免了事件频繁触发的问题。
效果说明
修改后,.nav-hover采用绝对定位,宽度变化不会影响父元素和容器的宽度,.buttons的固定宽度也让transform的偏移值保持稳定,快速hover时不会再出现元素偏移的问题,动画也会更流畅。
内容的提问来源于stack exchange,提问作者Tommaso Pagano
相关产品推荐
相关产品推荐

