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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 03:33:28