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

如何为React+TailwindCSS项目的汉堡菜单添加过渡动画?

为React+TailwindCSS的汉堡菜单添加过渡动画

我使用Vite、React与TailwindCSS开发项目,现有如下Navbar组件及App.jsx代码,希望为汉堡菜单添加平滑的展开/收起过渡动画,但尝试后未成功,请问该如何实现?

我的Navbar组件

import { useState } from 'react';
import { navlinks } from '../constants/constants';
import hmclose from '../assets/icons/hamburger_close.png';
import hm from '../assets/icons/hamburger.png';

const Navbar = () => {
  const [toggle, setToggle] = useState(false);

  return (
    <div className={`flex flex-col md:flex-row w-full mt-[24px] transition-height ${toggle ? 'h-auto' : 'h-[33px]'}`}>
      <nav className='flex items-center justify-center w-full'>
        <ul className='list-none md:flex hidden gap-[48px]'>
          {navlinks.map((navitem, index) => (
            <li key={index} className={`cursor-pointer text-[16px] text-accent`}>
              <a href="">{navitem.text}</a>
            </li>
          ))}
        </ul>
      </nav>

      <div className='flex px-[16px] gap-[16px]'>
        <button className="hidden md:flex bg-secondary text-primary py-[8px] px-[8px] rounded-[8px] outline-none items-center">
          Contact
        </button>
        <button className="hidden md:flex border-2 border-secondary text-accent bg-transparent py-[8px] px-[8px] rounded-[8px] outline-none items-center">
          Resume
        </button>
      </div>

      <div className='md:hidden flex px-[16px] gap-[16px]'>
        <img
          src={toggle ? hmclose : hm}
          alt="menu"
          className='w-[48px] h-[48px] object-contain'
          onClick={() => setToggle((prev) => !prev)}
        />
      </div>

      {toggle && (
        <div className='md:hidden flex flex-col w-full items-center justify-center'>
          <ul className='list-none text-center'>
            {navlinks.map((navitem, index) => (
              <li
                key={index}
                className={`cursor-pointer text-[16px] text-accent mb-4`}
              >
                <a href={`#${navitem.link}`}>{navitem.text}</a>
              </li>
            ))}
          </ul>
        </div>
      )}
    </div>
  );
};

export default Navbar;

我的App.jsx文件

import React from 'react'
import Navbar from './components/Navbar'

const App = () => {
  return (
    <div className="bg-primary w-full overflow-hidden">
    <div>
      <Navbar />
    </div>
  </div>
  )
}

export default App

解决方案

问题根源

  1. Tailwind的transition-height对h-auto无效,CSS无法过渡到自动高度
  2. 直接用{toggle && ...}控制菜单挂载/卸载,没有过渡时间,元素会直接出现/消失

修改步骤

  1. 用max-height代替height实现过渡:设置收起时max-h-0,展开时max-h-[500px](值要足够容纳菜单内容)
  2. 让移动端菜单始终存在,通过max-height和overflow-hidden控制显示隐藏
  3. 给菜单容器添加过渡类,确保动画平滑

修改后的Navbar组件

import { useState } from 'react';
import { navlinks } from '../constants/constants';
import hmclose from '../assets/icons/hamburger_close.png';
import hm from '../assets/icons/hamburger.png';

const Navbar = () => {
  const [toggle, setToggle] = useState(false);

  return (
    <div className="flex flex-col md:flex-row w-full mt-[24px]">
      {/* 桌面端导航栏 */}
      <nav className='flex items-center justify-center w-full'>
        <ul className='list-none md:flex hidden gap-[48px]'>
          {navlinks.map((navitem, index) => (
            <li key={index} className={`cursor-pointer text-[16px] text-accent`}>
              <a href="">{navitem.text}</a>
            </li>
          ))}
        </ul>
      </nav>

      {/* 桌面端按钮 */}
      <div className='flex px-[16px] gap-[16px]'>
        <button className="hidden md:flex bg-secondary text-primary py-[8px] px-[8px] rounded-[8px] outline-none items-center">
          Contact
        </button>
        <button className="hidden md:flex border-2 border-secondary text-accent bg-transparent py-[8px] px-[8px] rounded-[8px] outline-none items-center">
          Resume
        </button>
      </div>

      {/* 移动端汉堡按钮 */}
      <div className='md:hidden flex px-[16px] gap-[16px]'>
        <img
          src={toggle ? hmclose : hm}
          alt="menu"
          className='w-[48px] h-[48px] object-contain'
          onClick={() => setToggle((prev) => !prev)}
        />
      </div>

      {/* 移动端菜单(始终存在,通过max-height控制显示) */}
      <div className={`md:hidden flex flex-col w-full items-center justify-center overflow-hidden transition-all duration-300 ease-in-out ${toggle ? 'max-h-[500px]' : 'max-h-0'}`}>
        <ul className='list-none text-center py-4'>
          {navlinks.map((navitem, index) => (
            <li
              key={index}
              className={`cursor-pointer text-[16px] text-accent mb-4`}
            >
              <a href={`#${navitem.link}`}>{navitem.text}</a>
            </li>
          ))}
        </ul>
      </div>
    </div>
  );
};

export default Navbar;

关键修改说明

  • 移除了原容器的transition-height和动态height设置,max-height过渡更可靠
  • 移动端菜单不再用条件渲染,而是通过max-h-0(收起)和max-h-[500px](展开)控制,配合transition-all duration-300实现平滑过渡
  • 给菜单ul添加了py-4,避免收起时出现多余间距
  • 过渡动画的时长和缓动函数可以通过duration-*和ease-*类调整,比如duration-500改为500毫秒过渡

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 23:27:02