菜单关闭时CSS slide动画失效问题求助
解决侧边菜单关闭时列表项动画不触发的问题
问题原因
当前代码关闭菜单时,直接通过移除linksActive类让.pageLinks变回display: none,元素会立即从DOM中消失,导致关闭动画没有执行的时间窗口。同时,列表项的slide动画仅在元素首次渲染时触发,关闭过程中没有对应的触发逻辑。
解决方案
我们需要调整元素的隐藏方式,改用opacity和visibility配合过渡,同时添加反向动画,并通过JavaScript监听动画结束事件来控制元素最终的隐藏状态:
1. 修改CSS代码
body { background-color: #323232; position: relative; } @keyframes slide { 0% { opacity: 0.0; transform: translateY(50px) } 100% { opacity: 1.0; transform: translateY(0) } } /* 新增关闭时的反向动画 */ @keyframes slideOut { 0% { opacity: 1.0; transform: translateY(0) } 100% { opacity: 0.0; transform: translateY(50px) } } .pageLinks { /* 替换display:none为以下属性,保留过渡效果 */ opacity: 0; visibility: hidden; position: fixed; top: 5%; right: 50%; transition: opacity 0.3s ease, visibility 0.3s ease; } .pageLinks.linksActive { opacity: 1; visibility: visible; } .pageLinks ul { writing-mode: vertical-rl; transform: rotate(180deg); margin: 0; list-style: none; } .pageLinks ul li { float: left; margin: 20px 0px; } /* 打开菜单时触发的动画 */ .pageLinks.linksActive ul li { animation: slide 0.3s linear forwards; } /* 关闭菜单时触发的反向动画 */ .pageLinks.closing ul li { animation: slideOut 0.3s linear forwards; } .pageLinks ul li a { color: #DBDBDB; font-family: 'poppins', sans-serif; font-size: 16px; text-decoration: none; margin: 0; } .pageLinksButton { cursor: pointer; transition: transform 800ms; position: fixed; top: 0%; right: 49%; } .line { fill: none; transition: stroke-dasharray 800ms, stroke-dashoffset 800ms; stroke: #fff; stroke-width: 3; stroke-linecap: round; } .pageLinksButton.active { transform: rotate(-45deg); } .line:nth-child(1) { stroke-dasharray: 25 120; } .line:nth-child(3) { stroke-dasharray: 25 120; } .pageLinksButton.active .line:nth-child(1) { stroke-dashoffset: -90px; } .pageLinksButton.active .line:nth-child(3) { stroke-dashoffset: -90px; }
2. 修改JavaScript代码
const menu = document.querySelector('.pageLinksButton') const links = document.querySelector('.pageLinks') const menuItems = links.querySelectorAll('li') menu.addEventListener('click', () => { if (links.classList.contains('linksActive')) { // 关闭菜单:先触发反向动画,等动画结束后再隐藏 links.classList.add('closing') // 监听最后一个列表项的动画结束事件,确保所有动画完成 const lastItem = menuItems[menuItems.length - 1] lastItem.addEventListener('animationend', handleCloseEnd, { once: true }) } else { // 打开菜单:直接显示并触发入场动画 links.classList.add('linksActive') } menu.classList.toggle("active"); }) function handleCloseEnd() { links.classList.remove('linksActive', 'closing') }
3. HTML代码无需修改
<svg class="pageLinksButton hamRotate" viewBox="0 0 100 100" width="50"> <path class="line" d="m 70,33 h -40 c 0,0 -8.5,-0.149796 -8.5,8.5 0,8.649796 8.5,8.5 8.5,8.5 h 20 v -20" /> <path class="line" d="m 70,50 h -40" /> <path class="line" d="m 30,67 h 40 c 0,0 8.5,0.149796 8.5,-8.5 0,-8.649796 -8.5,-8.5 -8.5,-8.5 h -20 v 20" /> </svg> <nav class="pageLinks"> <ul> <li><a href="">Home</a></li> <li><a href="">Blog</a></li> <li><a href="">Contact</a></li> <li><a href="">About</a></li> </ul> </nav>
关键改动说明
- 用
opacity和visibility替代display: none,保证元素在动画执行期间仍处于DOM中 - 新增
slideOut反向动画,对应关闭时的列表项动效 - 通过
animationend事件监听动画完成状态,确保关闭动画执行完毕后再隐藏菜单 - 拆分打开和关闭的逻辑,分别触发对应的动画类
内容的提问来源于stack exchange,提问作者user20389275
相关产品推荐
相关产品推荐

