如何实现带列表滑动动画的菜单效果
实现悬停切换的滑动菜单效果
要实现鼠标悬停菜单项时内容列表在对应项下方显示,切换时平滑滑动并切换内容,我们可以通过CSS过渡结合JavaScript动态计算位置来完成,以下是完整实现方案:
核心思路
- 给每个菜单项绑定鼠标悬停事件,动态计算内容块的偏移位置,实现平滑滑动
- 为不同菜单项匹配对应的内容面板,切换时显示对应面板并隐藏其他
- 使用CSS的
transition属性实现位置和内容切换的平滑过渡
完整代码实现
HTML结构
调整结构,为每个菜单项绑定对应内容面板的标识:
<div class="wrapper"> <ul class="menu"> <li class="menu-item" data-target="content1">Item1</li> <li class="menu-item" data-target="content2">Item2</li> <li class="menu-item" data-target="content3">Item3</li> </ul> <div class="content-container"> <div class="content-panel" id="content1"> <div class="content-item">Item1-thing1</div> <div class="content-item">Item1-thing2</div> <div class="content-item">Item1-thing3</div> </div> <div class="content-panel" id="content2"> <div class="content-item">Item2-thing1</div> <div class="content-item">Item2-thing2</div> </div> <div class="content-panel" id="content3"> <div class="content-item">Item3-thing1</div> <div class="content-item">Item3-thing2</div> <div class="content-item">Item3-thing3</div> <div class="content-item">Item3-thing4</div> </div> </div> </div>
CSS样式
添加过渡效果、定位规则,初始隐藏内容面板:
.wrapper { position: relative; width: fit-content; } .menu { list-style: none; display: grid; grid-template-columns: repeat(3, min-content); column-gap: 30px; cursor: pointer; margin: 0; padding: 0; } .menu-item { padding: 8px 12px; } .content-container { position: absolute; top: 100%; left: 0; transition: transform 0.3s ease; } .content-panel { border: 1px solid grey; background: white; display: none; } .content-panel.active { display: block; } .content-item { padding: 10px 12px; cursor: pointer; } .content-item:hover { background-color: #f5f5f5; }
JavaScript逻辑
监听鼠标悬停事件,计算位置并切换对应内容:
const menuItems = document.querySelectorAll('.menu-item'); const contentContainer = document.querySelector('.content-container'); menuItems.forEach(item => { item.addEventListener('mouseover', () => { // 获取当前菜单项相对于容器的偏移量 const itemRect = item.getBoundingClientRect(); const wrapperRect = document.querySelector('.wrapper').getBoundingClientRect(); const offsetLeft = itemRect.left - wrapperRect.left; // 平滑滑动到对应位置 contentContainer.style.transform = `translateX(${offsetLeft}px)`; // 切换显示对应的内容面板 document.querySelectorAll('.content-panel').forEach(panel => { panel.classList.remove('active'); }); const targetPanel = document.getElementById(item.dataset.target); targetPanel.classList.add('active'); }); });
效果说明
- 鼠标悬停任意菜单项,内容容器会平滑滑动到该菜单项下方,同时显示对应内容
- 切换菜单项时,位置和内容的切换都带有0.3秒的平滑过渡
- 内容面板的宽度会自动适配内部内容,可根据需求修改为固定宽度
内容的提问来源于stack exchange,提问作者uiHellen
相关产品推荐
相关产品推荐

