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

React + Tailwind CSS 侧边栏菜单动画失效问题排查

问题

尝试用Tailwind CSS的transition-all duration-300 ease-in-out类实现侧边栏子菜单的开合动画,但动画未生效。代码如下:

{/* Submenü */}
{menu.submenu && submenuOpen === menuIndex && open && (
    <ul
        className={`transition-all duration-300 ease-in-out overflow-hidden ${submenuOpen ? 'max-h-full' : 'max-h-0'}`}
    >
        {menu.submenuItems!.filter(filteredSubMenu).map((submenuItem, subMenuIndex) => (
            <NavLink
                to={submenuItem.path ?? location.pathname}
                key={`menu-${menuIndex}-submenu-${subMenuIndex}`}
                className={`${subMenuitemClasses} ${selectedSubmenu.menuIndex === menuIndex && selectedSubmenu.subMenuIndex === subMenuIndex ? "bg-light-white" : ""}`}
                onClick={() => {
                    updateSelectedSubmenu(menuIndex, subMenuIndex);
                    setSelectedMenu(menuIndex);
                }}
            >
                {submenuItem.icon ? submenuItem.icon : <RiDashboardFill size={20} />}
                {submenuItem.title}
            </NavLink>
        ))}
    </ul>
)}

问题原因

  • DOM元素被卸载而非样式切换:外层的条件渲染会在不满足要求时直接把<ul>从DOM中移除,而非通过样式隐藏——元素都不存在了,自然无法触发过渡动画。
  • max-h-full的过渡计算问题:Tailwind的max-h-full对应max-height: 100%,浏览器无法准确计算从max-h-0到max-h-full的高度变化差值,导致动画失效。

解决方案

  1. 让<ul>始终保留在DOM中,通过样式控制显示/隐藏,而非条件渲染移除元素。
  2. 替换max-h-full为具体的、足够容纳子菜单内容的最大高度值(比如max-h-96,可根据实际需求调整),让浏览器能计算出明确的过渡差值。

修改后的代码:

{/* Submenü */}
<ul
    className={`transition-all duration-300 ease-in-out overflow-hidden ${
        menu.submenu && submenuOpen === menuIndex && open ? 'max-h-96' : 'max-h-0'
    }`}
>
    {menu.submenu && submenuOpen === menuIndex && open && menu.submenuItems!.filter(filteredSubMenu).map((submenuItem, subMenuIndex) => (
        <NavLink
            to={submenuItem.path ?? location.pathname}
            key={`menu-${menuIndex}-submenu-${subMenuIndex}`}
            className={`${subMenuitemClasses} ${selectedSubmenu.menuIndex === menuIndex && selectedSubmenu.subMenuIndex === subMenuIndex ? "bg-light-white" : ""}`}
            onClick={() => {
                updateSelectedSubmenu(menuIndex, subMenuIndex);
                setSelectedMenu(menuIndex);
            }}
        >
            {submenuItem.icon ? submenuItem.icon : <RiDashboardFill size={20} />}
            {submenuItem.title}
        </NavLink>
    ))}
</ul>

额外优化提示

  • 若子菜单高度不确定,可通过JavaScript动态计算内容高度后设置,但大多数场景下,设置一个足够大的固定max-h值已能满足需求。
  • 可以用transition-max-h替代transition-all,减少不必要的样式过渡开销,让动画更高效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 21:55:04