React中单个JSX元素的两个:focus-within选择器仅一个生效求助
问题原因与解决方案
问题根源
你的.blind元素和.menufocus是同级关系,但CSS中.menufocus:focus-within .blind使用的是后代选择器(空格分隔),只会匹配.menufocus内部的子元素,因此这个选择器无法选中页面上的.blind,导致样式不生效。
解决方案
方案1:调整DOM顺序 + 兄弟选择器
将.blind移到.menufocus之后,使用通用兄弟选择器~来匹配同级元素:
修改后的React代码:
return ( <div> <div className="menufocus" tabIndex={0}> <div className="menuicon"> <FontAwesomeIcon icon={solid("bars")} /> </div> <div className="dropdown"> <div className="dropitem">HOME</div> <div className="dropitem">ABOUT</div> <div className="dropitem">NEWS</div> <div className="dropitem">ICONHOLDERS</div> </div> </div> <div className="blind"></div> </div> );
修改后的CSS:
.menufocus:focus-within .dropdown { max-height: 18vh; } /* 使用通用兄弟选择器匹配同级的.blind */ .menufocus:focus-within ~ .blind { display: block; }
方案2:父元素聚焦控制(不调整DOM顺序)
给包裹.blind和.menufocus的父元素添加tabIndex,通过父元素的:focus-within来控制两个子元素:
修改后的React代码:
return ( <div className="menu-container" tabIndex={0}> <div className="blind"></div> <div className="menufocus"> <div className="menuicon"> <FontAwesomeIcon icon={solid("bars")} /> </div> <div className="dropdown"> <div className="dropitem">HOME</div> <div className="dropitem">ABOUT</div> <div className="dropitem">NEWS</div> <div className="dropitem">ICONHOLDERS</div> </div> </div> </div> );
修改后的CSS:
.menu-container:focus-within .dropdown { max-height: 18vh; } .menu-container:focus-within .blind { display: block; } /* 移除父元素默认聚焦边框(可选) */ .menu-container:focus { outline: none; }
方案3:React状态控制(灵活度最高)
使用useState管理菜单展开状态,通过事件触发状态切换,不受DOM结构限制:
修改后的React代码:
import { useState } from 'react'; // ... const [menuOpen, setMenuOpen] = useState(false); return ( <div> <div className={`blind ${menuOpen ? 'show' : ''}`}></div> <div className="menufocus" tabIndex={0} onFocus={() => setMenuOpen(true)} onBlur={() => setMenuOpen(false)} onClick={() => setMenuOpen(!menuOpen)} > <div className="menuicon"> <FontAwesomeIcon icon={solid("bars")} /> </div> <div className={`dropdown ${menuOpen ? 'expanded' : ''}`}> <div className="dropitem">HOME</div> <div className="dropitem">ABOUT</div> <div className="dropitem">NEWS</div> <div className="dropitem">ICONHOLDERS</div> </div> </div> </div> );
修改后的CSS:
.dropdown.expanded { max-height: 18vh; } .blind.show { display: block; }
方案对比
- 方案1:纯CSS实现,代码改动最小,但依赖DOM顺序。
- 方案2:纯CSS实现,不依赖DOM顺序,但需要父元素可聚焦。
- 方案3:React状态控制,支持更复杂交互(如点击遮罩关闭菜单),灵活度最高。
内容的提问来源于stack exchange,提问作者squarewatermeln
相关产品推荐
相关产品推荐

