防止:hover冒泡

9
如果我们悬停在子元素上,如何防止父元素的悬停效果?以下是代码:

const parent = document.getElementById('parent')
parent.onmouseover = function testAlert(e) {
  /* alert('parent') */
}
const childRight = document.getElementById('child-right')
childRight.onmouseover = function f(e) {
  e.stopPropagation()
  /* alert('child-right') */
}
const childLeft = document.getElementById('child-left')
childLeft.onmouseenter = function f(e) {
  e.stopPropagation()
  /* alert('child-right') */
}
#parent {
  background: green;
  width: 100px;
  height: 100px;
  position: relative;
  margin: 0 auto;
}

#parent:hover {
  background: rgba(0, 0, 0, 0.8);
}

#child-left {
  background: red;
  width: 50px;
  height: 50px;
  position: absolute;
  top: 0;
  left: -50px;
}

#child-right {
  background: red;
  width: 50px;
  height: 50px;
  position: absolute;
  top: 50px;
  left: 100px;
}
<div id="parent">
  <div id="child-left"></div>
  <div id="child-right"></div>
</div>

https://jsfiddle.net/3tjcsyov/48/

您可以看到,如果考虑CSS的行为,在悬停在红色矩形上时,绿色矩形也会被悬停。是的,我们可以使用stopPropagation,但它仅防止父元素执行JS处理程序,而CSS行为保持不变。


1
你能否使用JavaScript而不是SCSS来添加这个行为? - Jack Bashford
2
要悬停在子元素上,您必须悬停在父元素上。我不知道这种状态能否被防止。 - Taplar
1
请勿使用外部代码网站,除非 Stack Overflow 的代码片段功能不足。 - connexo
1
请在问题本身发布您的代码。 - AndrewL64
2
@TemaniAfif 这个问题并不太宽泛。这个答案 https://dev59.com/W7Hma4cB1Zd3GeqPP7ow#54604384/ 符合 OP 描述的要求。 - guest271314
显示剩余14条评论
2个回答

9

如果你将子元素的pointer-events设置为none,你可以在不使用任何JavaScript的情况下实现这一点。

#parent {
  background: green;
  width: 100px;
  height: 100px;
  position: relative;
  margin: 0 auto;
}

#parent:hover {
  background: rgba(0, 0, 0, 0.8);
}

#child-left {
  background: red;
  width: 50px;
  height: 50px;
  position: absolute;
  top: 0;
  left: -50px;
}

#child-right {
  background: red;
  width: 50px;
  height: 50px;
  position: absolute;
  top: 50px;
  left: 100px;
}

#child-left,
#child-right {
  pointer-events: none;
}
<div id="parent">
  <div id="child-left"></div>
  <div id="child-right"></div>
</div>

https://jsfiddle.net/bepLktoj/


2
移动鼠标时屏幕闪烁。 - Vaibhav Vishal
1
@VaibhavVishal 已修复。 - Andy Hoffman
1
这将从子元素中移除悬停。 - Temani Afif
1
@TemaniAfif 这不是一个要求。原始代码中子元素上没有 hover - Andy Hoffman
1
我知道,这只是一个简单的评论,说我们已经删除了所有的悬停而不仅仅是悬停传播。 - Temani Afif

2
当您只想在悬停于 #parent 时应用 hover 样式(且任一子元素悬停时不应用 hover 样式)的简单情况下,使用 pointer-events:none 与 #child-left 和 #child-right 选择器应该足够。只需将以下代码添加到您的样式表中即可实现:
#child-left,
#child-right {
  pointer-events: none;
}

对于更高级的情况(需要为此“父子场景”中的每个元素都提供不同的悬停样式),我的理解是在这里需要使用脚本,因为样式是从父级到子级而不是从子级到父级。

实现这一点的一个解决方案是引入一个 .hover 修饰符类来模仿内置的 :hover 选择器。该 .hover 类将包含您要应用于特定元素的唯一样式。您的脚本将根据鼠标交互添加或删除悬停类。

实现您所需的简单脚本是向 event#target 元素添加/删除 hover 类,该元素由传递给 mouseovermouseout 事件的 Event 对象提供:

const parent = document.getElementById('parent');

/*
Add mouse over and mouse out event listeners to 
add/remove hover class from the event's target element
*/

parent.addEventListener('mouseover', (event) => {
  /* 
  event.target is the actual element that triggers this 
  mouse event (ie the #parent or either of the children)
  */
  event.target.classList.add('hover'); 
})

parent.addEventListener('mouseout', (event) => {
  /* 
  event.target is the actual element that triggers this 
  mouse event (ie the #parent or either of the children)
  */     
  event.target.classList.remove('hover'); 
})
#parent {
  background: green;
  width: 100px;
  height: 100px;
  position: relative;
  margin: 0 auto;
}

#child-right {
  background: red;
  width: 50px;
  height: 50px;
  position: absolute;
  top: 50px;
  left: 100px;
}

#child-left {
  background: red;
  width: 50px;
  height: 50px;
  position: absolute;
  top: 0;
  left: -50px;  
}

/*
Introduce hover modified class, which is toggled
via javascript and substitutes the native CSS 
:hover selector. I've explicity defined a selector 
for each element however via SCSS this can be 
simplified */
#parent.hover,
#child-left.hover,
#child-right.hover {
  background: rgba(0,0,0,0.8);
}
<div id="parent">
  <div id="child-left"></div>
  <div id="child-right"></div>
</div>


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接