You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

菜单关闭时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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 03:01:09