React+Hooks点击汉堡图标添加className后Sass样式不生效求助
React Hooks添加className后Sass样式不生效问题解决
问题描述
尝试通过React Hooks实现点击汉堡图标时添加open类,在Sass中针对该类编写样式切换导航栏状态。目前open类已正确添加到元素上,但对应的样式并未生效。本人是Sass和React新手,已尝试调整样式嵌套方式,附上相关代码。
React组件代码
import { useContext, useState } from "react"; import { Link } from "react-router-dom"; import classes from "./styles/MainNavigation.module.css"; import FavoritesContext from "../../store/favorites-context"; function MainNaviagtion() { const [isOpen, setOpen] = useState(false); const favoriteCtx = useContext(FavoritesContext); const mobileMenuHandler = () => { setOpen(!isOpen); }; return ( <header className={classes.header}> <div className={classes.logo}>Meet Up Tracker</div> <nav> <ul id={classes.menu}> <li> <Link className={classes.link} to="/"> All Meetups </Link> </li> <li> <Link className={classes.link} to="/new-meetups"> New Meetups </Link> </li> <li> <Link className={classes.link} to="/favorites"> My Favorites <span className={classes.badge}> {favoriteCtx.totalFavorites} </span> </Link> </li> </ul> </nav> <div id={classes.hamburgerIcon} onClick={mobileMenuHandler} className={isOpen ? 'open' : null}> <div className={classes.bar1}></div> <div className={classes.bar2}></div> <div className={classes.bar3}></div> <ul className={classes.mobileMenu}> <li> <Link className={classes.link} to="/"> All Meetups </Link> </li> <li> <Link className={classes.link} to="/new-meetups"> New Meetups </Link> </li> <li> <Link className={classes.link} to="/favorites"> My Favorites <span className={classes.badge}> {favoriteCtx.totalFavorites} </span> </Link> </li> </ul> </div> </header> ); } export default MainNaviagtion;
Sass样式代码
$mobile: 576px; $tablet: 768px; $laptop: 992px; $desktop: 1200px; .header { width: 100%; height: 5rem; display: flex; align-items: center; justify-content: space-between; background-color: #77002e; padding: 0 10%; .logo { font-size: 30px; color: white; font-weight: bold; } .badge { background-color: #cc2062; color: white; border-radius: 12px; padding: 0 1rem; margin-left: 0.5rem; } } #hamburgerIcon { margin: auto 0; display: none; cursor: pointer; div { width: 35px; height: 3px; background-color: #fff; margin: 6px 0; transition: 0.4s; } } .open { .bar1 { -webkit-transform: rotate(-45deg) translate(-6px, 6px); transform: rotate(-45deg) translate(-6px, 6px); } .bar2 { opacity: 0; } .bar3 { -webkit-transform: rotate(45deg) translate(-6px, -8px); transform: rotate(45deg) translate(-6px, -8px); } .mobile-menu { display: flex; flex-direction: column; align-items: center; justify-content: flex-start; } } .mobileMenu { display: none; position: absolute; top: 50px; left: 0; height: calc(100vh - 50px); width: 100%; } .header ul { list-style: none; margin: 0; padding: 0; display: -webkit-inline-box; align-items: baseline; } .header li { margin-left: 3rem; } .header a { text-decoration: none; font-size: 20px; color: #fcb8d2; } .header a:hover, .header a:active, .header a.active { color: white; } @media (max-width: $tablet) { .header { .logo { font-size: 25px; } .link { display: flex; align-items: center; font-size: 15px; border: 2px solid black; } } .header ul { display: -webkit-inline-box; } .header li { margin-left: 1rem; } } @media (max-width: $mobile) { #menu { display: none; } #hamburgerIcon { display: block !important; } }
问题原因
- CSS Modules类隔离:使用了CSS Modules(从
import classes from "./styles/MainNavigation.module.css"可看出),手动添加的open是全局类,而CSS Modules会将局部类名编译成唯一标识,全局类需要用:global()包裹才能匹配到元素。 - 选择器命名不匹配:Sass中写的是
.mobile-menu,但React组件中用的是classes.mobileMenu,编译后的类名是模块化格式,两者无法对应。 - 样式优先级冲突:
#hamburgerIcon的ID选择器优先级比.open类选择器高,导致.open下的bar样式被基础样式覆盖。
解决方案
1. 适配CSS Modules的全局类处理
将Sass中的.open选择器嵌套到汉堡图标的类下,并用:global()标记open类:
.hamburgerIcon { margin: auto 0; display: none; cursor: pointer; div { width: 35px; height: 3px; background-color: #fff; margin: 6px 0; transition: 0.4s; } &:global(.open) { .bar1 { -webkit-transform: rotate(-45deg) translate(-6px, 6px); transform: rotate(-45deg) translate(-6px, 6px); } .bar2 { opacity: 0; } .bar3 { -webkit-transform: rotate(45deg) translate(-6px, -8px); transform: rotate(45deg) translate(-6px, -8px); } .mobileMenu { display: flex; flex-direction: column; align-items: center; justify-content: flex-start; } } }
2. 修正React组件的className写法
将汉堡图标的ID改为className,并正确拼接open类:
<div className={`${classes.hamburgerIcon} ${isOpen ? 'open' : ''}`} onClick={mobileMenuHandler} > <div className={classes.bar1}></div> <div className={classes.bar2}></div> <div className={classes.bar3}></div> <ul className={classes.mobileMenu}> {/* 菜单内容 */} </ul> </div>
3. 统一选择器命名与优先级
将Sass中的#hamburgerIcon和#menu改为className,避免ID带来的高优先级冲突:
.menu { list-style: none; margin: 0; padding: 0; display: -webkit-inline-box; align-items: baseline; } @media (max-width: $mobile) { .menu { display: none; } .hamburgerIcon { display: block !important; } }
同时修改React组件中的ul部分:
<nav> <ul className={classes.menu}> {/* 菜单内容 */} </ul> </nav>
内容的提问来源于stack exchange,提问作者Alewdy Silvestre
相关产品推荐
相关产品推荐

