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

React中汉堡菜单切换open类失效问题求助

汉堡菜单切换"open"类无效的问题解决

问题描述

尝试在汉堡图标上切换“open”类以显示移动端菜单,但未达到预期效果。汉堡图标仅在小屏幕(≤1080px)显示,使用React的useState钩子修改类名却未生效。

原JSX代码

import "./header.css";
import { useState } from "react";

function Header() {
  const [hamState, setHamState] = useState(false);

  function abrirMenu() {
    console.log("click");
    setHamState((hamState) => !hamState);
  }
  let openMenu = hamState ? "open" : "";
  return (
    <div>
      <header>
        <div className="menu">
          <div className={`navbar ${openMenu}`}>
            <ul>
              <li>
                <a href="#recuperacao">É difícil ser programador?</a>
              </li>
              <li>
                <a href="#sobre">Se torne um programador</a>
              </li>
              <li>
                <a href="#depoimentos">Veja o que diz quem já fez</a>
              </li>
            </ul>
          </div>

          <input type="checkbox" id="hamburguer" />
          <label htmlFor="hamburguer">
            <div className="hamburguer" onClick={abrirMenu}></div>
          </label>
        </div>
      </header>
    </div>
  );
}

export default Header;

原CSS代码

.container {
  padding: 0 2%;
  display: flex;
  margin: 0 auto;
  max-width: 1280px;
}
.menu {
  text-align: center;
  padding: 11px 0 10px 0;
  display: flex;
  box-shadow: 0px 1px 5px 0px rgba(0, 0, 0, 0.75);
  -webkit-box-shadow: 0px 1px 5px 0px rgba(0, 0, 0, 0.75);
  -moz-box-shadow: 0px 1px 5px 0px rgba(0, 0, 0, 0.75);
}
.navbar {
  margin: 0 auto;
}
.navbar ul {
  width: 100%;
  padding: 20px 0;
  list-style: none;
}
.navbar li {
  display: inline;
  padding: 0 60px;
}
.navbar li a {
  font-size: 18px;
  text-decoration: none;
  color: rgb(105, 1, 190);
  font-weight: bold;
  transition: 0.5s ease;
}
.navbar li a:hover {
  color: rgb(140, 0, 255);
}
input[type="checkbox"] {
  display: none;
}
.hamburguer {
  display: none;
  width: 70px;
  height: 70px;
  position: fixed;
  top: 20px;
  right: 0;
  cursor: pointer;
}

.hamburguer::after {
  content: "";
  position: absolute;
  width: 70%;
  height: 10%;
  background-color: rgb(255, 255, 255);
  border-radius: 20px;
  top: 30%;
  left: 15%;
  transition: 1s ease;
}
.hamburguer::before {
  content: "";
  position: absolute;
  width: 50%;
  height: 10%;
  background-color: rgb(255, 255, 255);
  border-radius: 20px;
  top: 50%;
  left: 35%;
  transition: 1s ease;
}
#hamburguer:checked ~ label .hamburguer::after {
  transform: rotate(225deg);
  top: 45%;
  background-color: white;
}
#hamburguer:checked ~ label .hamburguer::before {
  transform: rotate(-225deg);
  left: 15%;
  width: 70%;
  top: 45%;
  background-color: white;
}
@media screen and (max-width: 1080px) {
  .logo {
    width: 40%;
  }
  .navbar ul {
    position: fixed;
    top: 100px;
    right: 0;
    width: 60%;
    height: 100%;
    display: flex;
    justify-content: center;
    align-items: center;
    flex-direction: column;
    background-color: red;
    transition: transform 0.6s ease-in;
    transform: translateX(100%);
  }
  .open {
    transform: translateX(0);
  }
  .navbar ul li {
    padding: 15px 0;
  }
  .navbar ul li a {
    color: white;
    transition: 0.3s ease-in;
  }
  .navbar ul li a:hover {
    color: white;
  }
  .hamburguer {
    display: inline-block;
  }
}

问题原因及解决方案

核心问题

  1. 类名挂载位置错误:你把open类加到了.navbar上,但CSS中控制菜单显示的.open选择器是直接作用于ul元素的,两者不匹配。
  2. 控制逻辑冲突:同时使用了checkbox伪类和React useState两种逻辑控制菜单,导致状态不同步,干扰了最终效果。

修改后的代码

JSX代码

import "./header.css";
import { useState } from "react";

function Header() {
  const [hamState, setHamState] = useState(false);

  function abrirMenu() {
    setHamState(prev => !prev);
  }
  
  return (
    <div>
      <header>
        <div className="menu">
          <div className="navbar">
            {/* 将open类移到ul元素上 */}
            <ul className={hamState ? "open" : ""}>
              <li>
                <a href="#recuperacao">É difícil ser programador?</a>
              </li>
              <li>
                <a href="#sobre">Se torne um programador</a>
              </li>
              <li>
                <a href="#depoimentos">Veja o que diz quem já fez</a>
              </li>
            </ul>
          </div>

          {/* 用active类控制汉堡图标变形,移除checkbox逻辑 */}
          <div className={`hamburguer ${hamState ? "active" : ""}`} onClick={abrirMenu}></div>
        </div>
      </header>
    </div>
  );
}

export default Header;

CSS代码(关键修改部分)

/* 替换原checkbox相关样式,用active类控制汉堡图标 */
.hamburguer.active::after {
  transform: rotate(225deg);
  top: 45%;
  background-color: white;
}
.hamburguer.active::before {
  transform: rotate(-225deg);
  left: 15%;
  width: 70%;
  top: 45%;
  background-color: white;
}

@media screen and (max-width: 1080px) {
  /* 修改.open选择器的作用对象,匹配ul元素 */
  .navbar ul.open {
    transform: translateX(0);
  }
}

修改说明

  1. 把open类从.navbar移到ul上,确保和CSS中控制菜单位移的选择器匹配。
  2. 移除checkbox和label的冗余逻辑,统一用React状态控制菜单显示/隐藏以及汉堡图标的变形效果。
  3. 用.active类替代checkbox伪类控制汉堡图标的样式,保证状态同步。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 04:02:03