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

CSS+TypeScript移动端菜单侧滑动画:关闭无动画问题求助

移动端菜单关闭动画不生效的解决思路

问题根源

你当前的实现中,关闭菜单时通过isMobileMenuOpen &&直接移除了菜单内的<ul>元素,同时切换dismiss类触发动画。但元素内容被立即移除,导致动画还未执行完成就失去了载体,所以关闭动画直接跳转到结束状态。另外,外层按钮嵌套内层按钮的HTML结构是无效的,可能会干扰点击事件和渲染逻辑。

具体解决步骤

  • 移除无效的按钮嵌套结构
    把内层的<button>替换为直接渲染图标,避免HTML语义错误:

    {/* Mobile Menu */}
    <div className="lg:hidden">
      <button className="flex items-center w-8" onClick={toggleMenu}>
        {isMobileMenuOpen ? 
          <AiOutlineUp className="w-full h-full" /> : 
          <AiOutlineDown className="w-full h-full" />
        }
      </button>
    </div>
    
  • 保留菜单DOM结构,不通过条件渲染移除内容
    始终渲染菜单内的<ul>,用CSS类控制动画和可见性,而不是直接删除元素:

    {/* Mobile Menu Items */}
    <div
      className={`mobileMenu lg:hidden p-10 bg-[#101010] ${
        isMobileMenuOpen ? "selected" : "dismiss"
      }`}
    >
      <ul className="flex flex-col gap-4 text-[22px]">
        {renderNavLinks(navLinks)}
      </ul>
    </div>
    
  • 调整CSS动画逻辑,确保关闭动画有完整执行周期
    优化关键帧动画的触发逻辑,让菜单在基础状态下保持可动画的属性:

    @keyframes slidein {
      from { transform: translateY(-100%); opacity: 0; }
      to { transform: translateY(0); opacity: 1; }
    }
    
    @keyframes slideout {
      from { transform: translateY(0); opacity: 1; }
      to { transform: translateY(-100%); opacity: 0; }
    }
    
    .mobileMenu {
      transform: translateY(-100%);
      opacity: 0;
      overflow: hidden;
    }
    
    .mobileMenu.selected {
      animation: slidein 0.3s forwards;
    }
    
    .mobileMenu.dismiss {
      animation: slideout 0.3s forwards;
    }
    
  • 监听动画结束事件,控制最终隐藏状态
    如果需要动画结束后完全隐藏菜单(比如设置display: none),可以通过animationend事件延迟处理:

    import { useState } from 'react';
    
    const [isMenuHidden, setIsMenuHidden] = useState(true);
    
    const toggleMenu = () => {
      if (isMobileMenuOpen) {
        // 关闭菜单时先显示元素,触发动画
        setIsMenuHidden(false);
        setIsMobileMenuOpen(false);
      } else {
        setIsMobileMenuOpen(true);
        setIsMenuHidden(false);
      }
    };
    
    const handleAnimationEnd = (e: AnimationEvent) => {
      if (e.animationName === 'slideout' && !isMobileMenuOpen) {
        // 动画结束后隐藏元素
        setIsMenuHidden(true);
      }
    };
    
    // 菜单元素修改
    <div
      className={`mobileMenu lg:hidden p-10 bg-[#101010] ${
        isMobileMenuOpen ? "selected" : "dismiss"
      } ${isMenuHidden ? 'hidden' : ''}`}
      onAnimationEnd={handleAnimationEnd}
    >
      <ul className="flex flex-col gap-4 text-[22px]">
        {renderNavLinks(navLinks)}
      </ul>
    </div>
    
  • 改用CSS Transition替代关键帧(更简洁方案)
    如果不需要复杂的关键帧动画,用transition可以更稳定地实现滑入滑出,且无需额外事件监听:

    .mobileMenu {
      transform: translateY(-100%);
      opacity: 0;
      transition: transform 0.3s ease, opacity 0.3s ease;
      overflow: hidden;
    }
    
    .mobileMenu.selected {
      transform: translateY(0);
      opacity: 1;
    }
    
    .mobileMenu.dismiss {
      transform: translateY(-100%);
      opacity: 0;
    }
    

内容的提问来源于stack exchange,提问作者salm00n

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 11:57:05