React+CSS:如何禁用上层元素覆盖时下方单元格的hover效果?
嘿,刚上手React和CSS遇到这种视觉交互问题很正常,我来给你两个简单可行的方案,帮你搞定这个问题~
方案一:用CSS :has() 选择器(最简洁,适合现代浏览器)
这个方案不需要改太多React代码,纯CSS就能解决。核心思路是:只有当单元格里没有CalEventCard的时候,才触发hover高亮。
首先给你的CalEventCard加一个专属类名,比如cal-event-card:
<Card className="cal-event-card" sx={{ zIndex: 1, position: 'absolute', // 你的其他sx配置... }} >
然后修改原来的hover CSS规则,用:not(:has(.cal-event-card))来排除包含卡片的单元格和列:
/* 只有当weekdayList里没有cal-event-card时,hover才生效 */ .weekdayList:not(:has(.cal-event-card)):hover { background-color: rgba(33, 149, 243, 0.15); } /* 只有当hourCell里没有cal-event-card时,hover才生效 */ .hourCell:not(:has(.cal-event-card)):hover { background-color: rgba(33, 149, 243, 0.15); }
注意:
:has()选择器目前已经被Chrome、Edge、Safari支持,Firefox需要在about:config里开启layout.css.has-selector.enabled才能生效。如果你的项目需要兼容旧版Firefox,可以看下面的方案二。
方案二:用React状态控制hover禁用(全浏览器兼容)
如果需要兼容不支持:has()的浏览器,我们可以通过React状态来追踪鼠标是否悬停在卡片上,动态给单元格添加“禁用hover”的类。
步骤1:在父组件中添加状态
import { useState } from 'react'; // 父组件里定义状态 const [isHoveringCard, setIsHoveringCard] = useState(false);
步骤2:给CalEventCard绑定鼠标事件
把状态更新函数传递给CalEventCard,监听鼠标进入和离开事件:
<div className="weekdayList"> {/* 你的循环代码 */} <div className={`hourCell ${isHoveringCard ? 'no-hover' : ''}`}> {checkEventExists && ( <CalEventCard onMouseEnter={() => setIsHoveringCard(true)} onMouseLeave={() => setIsHoveringCard(false)} /> )} <Button>button with action</Button> </div> </div>
注意:如果你的
weekdayList里有多个hourCell,可能需要把状态改成针对单个单元格的(比如用事件对象或者单元格ID来区分),避免悬停一个卡片时所有单元格都禁用hover。
步骤3:修改CSS规则
给原来的hover规则加上:not(.no-hover),排除掉带有no-hover类的元素:
.weekdayList:hover:not(.no-hover), .hourCell:hover:not(.no-hover) { background-color: rgba(33, 149, 243, 0.15); }
为什么你之前试的pointer-events没生效?
你提到试过pointer-events,可能是用法不对:如果给CalEventCard设置pointer-events: auto(默认就是auto),鼠标事件会被卡片捕获,但hover伪类是基于鼠标位置的,即使卡片在上面,浏览器还是会检测到鼠标在下面的单元格上,所以hover还是会触发。如果给单元格设置pointer-events: none,虽然能禁用hover,但单元格里的按钮也会失去点击能力,这显然不是你想要的。所以上面两个方案更适合你的场景~
内容的提问来源于stack exchange,提问作者byte89

