技术求助:为Vertical Menu实现跟随选中区域的垂直线效果
实现跟随菜单项的滑动垂直线效果
我完全理解你想要的效果——一条能平滑跟随hover或选中菜单项滑动的垂直线,而不是简单的颜色切换。下面给你两种实现方案,分别适合固定菜单和动态菜单场景:
方案一:纯CSS实现(适合固定数量的菜单)
这种方案不需要JavaScript,通过CSS选择器和过渡动画就能实现滑动效果,代码简洁直观:
HTML代码
<div id="nav"> <ul> <li class="active"><a href="#">Example 1</a></li> <li><a href="#">Example 2</a></li> <li><a href="#">Example 3</a></li> <li><a href="#">Example 4</a></li> </ul> </div>
CSS代码
#nav { width: 220px; background-color: #f0f0f0; } #nav ul { list-style: none; margin: 0; padding: 0; position: relative; /* 作为滑动线的定位基准 */ } /* 定义滑动垂直线 */ #nav ul::before { content: ''; position: absolute; left: 0; top: 0; width: 4px; height: 44px; /* 和单个菜单项高度一致 */ background-color: #2563eb; /* 你想要的垂直线颜色 */ transition: top 0.3s ease; /* 0.3秒平滑过渡 */ } #nav li { height: 44px; line-height: 44px; padding-left: 24px; cursor: pointer; transition: background-color 0.2s; } #nav li:hover { background-color: #e5e7eb; } #nav li a { color: #333; text-decoration: none; display: block; } /* 为每个菜单项hover时设置滑动线位置 */ #nav li:nth-child(1):hover ~ ::before { top: 0; } #nav li:nth-child(2):hover ~ ::before { top: 44px; } #nav li:nth-child(3):hover ~ ::before { top: 88px; } #nav li:nth-child(4):hover ~ ::before { top: 132px; } /* 保持active项的滑动线位置 */ #nav li.active:nth-child(1) ~ ::before { top: 0; } #nav li.active:nth-child(2) ~ ::before { top: 44px; } #nav li.active:nth-child(3) ~ ::before { top: 88px; } #nav li.active:nth-child(4) ~ ::before { top: 132px; }
方案二:CSS + JavaScript实现(适合动态菜单)
如果你的菜单项是动态生成的,纯CSS方案就不适用了,这时用JS动态计算位置会更灵活:
HTML代码
<div id="nav"> <ul> <!-- 滑动线元素 --> <div class="slider"></div> <li class="active"><a href="#">Example 1</a></li> <li><a href="#">Example 2</a></li> <li><a href="#">Example 3</a></li> <li><a href="#">Example 4</a></li> </ul> </div>
CSS代码
#nav { width: 220px; background-color: #f0f0f0; } #nav ul { list-style: none; margin: 0; padding: 0; position: relative; } #nav ul .slider { position: absolute; left: 0; width: 4px; background-color: #2563eb; transition: top 0.3s ease, height 0.3s ease; /* 支持高度和位置的过渡 */ } #nav li { height: 44px; line-height: 44px; padding-left: 24px; cursor: pointer; transition: background-color 0.2s; } #nav li:hover { background-color: #e5e7eb; } #nav li a { color: #333; text-decoration: none; display: block; }
JavaScript代码
const navUl = document.querySelector('#nav ul'); const navItems = navUl.querySelectorAll('li'); const slider = navUl.querySelector('.slider'); // 设置滑动线位置的核心函数 function setSliderPosition(targetItem) { const itemRect = targetItem.getBoundingClientRect(); const ulRect = navUl.getBoundingClientRect(); // 计算滑动线相对于ul的top值和高度 slider.style.top = `${itemRect.top - ulRect.top}px`; slider.style.height = `${itemRect.height}px`; } // 初始化:设置active项的滑动线位置 const initialActiveItem = navUl.querySelector('.active'); if (initialActiveItem) { setSliderPosition(initialActiveItem); } // 监听每个菜单项的hover事件 navItems.forEach(item => { item.addEventListener('mouseover', () => { setSliderPosition(item); }); // 点击菜单项时设置active状态 item.addEventListener('click', (e) => { e.preventDefault(); // 移除所有项的active类 navItems.forEach(i => i.classList.remove('active')); // 给当前项添加active类 item.classList.add('active'); // 更新滑动线位置 setSliderPosition(item); }); });
关键原理说明
- 定位基准:给
ul设置position: relative,让滑动线(绝对定位)以ul为基准定位 - 过渡动画:通过
transition属性实现滑动线的平滑移动,提升用户体验 - 动态计算:JS方案中使用
getBoundingClientRect()获取元素的位置和尺寸,确保滑动线能精准匹配任何菜单项
内容的提问来源于stack exchange,提问作者Eugene2018
相关产品推荐
相关产品推荐

