React中用isOpen状态替换group-focus后汉堡菜单X图标不显示
修复React+Tailwind汉堡菜单切换时X图标显示异常的问题
我把Tailwind的group-focus替换为React的isOpen状态实现汉堡菜单切换,参考了第7号图标效果。替换逻辑后,点击按钮时X图标要么完全不出现,要么和汉堡图标同时显示,视觉上没切换成功。
我的代码如下:
import React, { useState } from "react"; export default function HamburgerIcon() { const [isOpen, setIsOpen] = useState(false); const toggleMenu = () => { setIsOpen(!isOpen); }; return ( <div> <button className={`relative group ${isOpen ? "focus:ring-4" : ""}`} onClick={toggleMenu}> <div className={`relative flex overflow-hidden items-center justify-center rounded-full w-[50px] h-[50px] transform transition-all ring-0 ring-secondary hover:ring-8 duration-200 shadow-md ${isOpen ? "ring-4" : ""}`}> <div className={`flex flex-col justify-between w-[20px] h-[20px] transform transition-all duration-300 origin-center overflow-hidden`}> {/*This is div as Hamburger */} <div className={`bg-font-color h-[2px] w-7 transform transition-all duration-300 origin-left ${isOpen ? "rotate-45 translate-y-6 delay-100" : ""}`}></div> <div className={`bg-font-color h-[2px] w-7 rounded transform transition-all duration-300 ${isOpen ? "translate-y-6 delay-75" : ""}`}></div> <div className={`bg-font-color h-[2px] w-7 transform transition-all duration-300 origin-left ${isOpen ? "translate-y-6" : ""}`}></div> {/*This is div with X*/} <div className={`absolute items-center justify-between transform transition-all duration-500 top-2.5 ${isOpen ? "-translate-x-10" : "translate-x-0"} flex w-0 ${isOpen ? "w-12" : ""}`}> <div className={`absolute bg-font-color h-[2px] w-5 transform transition-all duration-500 ${isOpen ? "rotate-45 delay-300" : ""}`}></div> <div className={`absolute bg-font-color h-[2px] w-5 transform transition-all duration-500 ${isOpen ? "-rotate-45 delay-300" : ""}`}></div> </div> </div> </div> </button> </div> ); }
效果截图:
问题根源
- 汉堡图标未隐藏:
isOpen状态下,汉堡的三个bar仅做了位移和旋转,未设置隐藏逻辑,导致和X图标重叠,视觉上X像没显示 - X图标过渡逻辑错误:X图标的位移方向搞反,关闭状态下未正确隐藏,且宽度与位移过渡时机不匹配
修复后的代码
import React, { useState } from "react"; export default function HamburgerIcon() { const [isOpen, setIsOpen] = useState(false); const toggleMenu = () => { setIsOpen(!isOpen); }; return ( <div> <button className={`relative group`} onClick={toggleMenu}> <div className={`relative flex overflow-hidden items-center justify-center rounded-full w-[50px] h-[50px] transform transition-all ring-0 ring-secondary hover:ring-8 duration-200 shadow-md ${isOpen ? "ring-4" : ""}`}> {/* 汉堡图标容器:打开时隐藏 */} <div className={`flex flex-col justify-between w-[20px] h-[20px] transform transition-all duration-300 origin-center overflow-hidden ${isOpen ? "opacity-0 h-0" : ""}`}> <div className={`bg-font-color h-[2px] w-7 transform transition-all duration-300 origin-left ${isOpen ? "rotate-45 translate-y-6 delay-100" : ""}`}></div> <div className={`bg-font-color h-[2px] w-7 rounded transform transition-all duration-300 ${isOpen ? "translate-y-6 delay-75" : ""}`}></div> <div className={`bg-font-color h-[2px] w-7 transform transition-all duration-300 origin-left ${isOpen ? "-rotate-45 translate-y-6 delay-100" : ""}`}></div> </div> {/* X图标容器:打开时显示,关闭时隐藏 */} <div className={`absolute items-center justify-center transform transition-all duration-500 top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 flex w-0 ${isOpen ? "w-10 opacity-100" : "opacity-0"}`}> <div className={`bg-font-color h-[2px] w-5 transform transition-all duration-300 delay-200 ${isOpen ? "rotate-45" : ""}`}></div> <div className={`bg-font-color h-[2px] w-5 transform transition-all duration-300 delay-200 ${isOpen ? "-rotate-45" : ""}`}></div> </div> </div> </button> </div> ); }
关键修改点
- 汉堡图标添加隐藏逻辑:
isOpen状态下给汉堡容器加opacity-0 h-0,让汉堡平滑消失,避免与X重叠 - 重构X图标定位:用
top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2实现X图标居中,解决原定位偏移问题 - 调整X图标过渡逻辑:关闭状态下用
opacity-0 w-0隐藏,打开时用opacity-100 w-10显示,配合delay让动画衔接自然 - 修正汉堡第三个bar的旋转方向:给第三个bar加上
-rotate-45,让汉堡展开动画更合理 - 移除冗余focus类:
isOpen状态下的focus:ring-4无需保留,按钮的ring状态直接通过isOpen控制即可
内容的提问来源于stack exchange,提问作者Peter_Griffindor
相关产品推荐
相关产品推荐

