javascript 防止 CSS :hover 样式传播

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25246472/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-28 04:14:27  来源:igfitidea点击:

Prevent CSS :hover style propagation

javascriptjqueryhtmlcssmouseover

提问by zok

In the following example, when I mouse over the 'X' button, the list-item hoverstyle gets enabled as well, I do not want this to happen.

在以下示例中,当我将鼠标悬停在“X”按钮上时,列表项hover样式也会启用,我不希望发生这种情况。

Is it possible to have a hoverstyle on the button independent of the hoverstyle on the list-group-item? Something like prevent the 'hover' propagation?

是否可以hover在按钮上设置独立于 上的hover样式的样式list-group-item?诸如防止“悬停”传播之类的东西?

Is there any other way to achieve that? Maybe assembling all of this HTML/CSS/JS in a different way?

有没有其他方法可以实现这一目标?也许以不同的方式组装所有这些 HTML/CSS/JS?

Working sample here

工作样本在这里

<ul class="list-group">
  <li class="list-group-item">
    Lalalalaiaia
                <button class="btn btn-default btn-xs pull-right remove-item">
      <span class="glyphicon glyphicon-remove"></span>
    </button>
  </li>
  <li class="list-group-item">
    Panananannaeue 
                <button class="btn btn-default btn-xs pull-right remove-item">
      <span class="glyphicon glyphicon-remove"></span>
    </button>
  </li>
</ul>

CSS

CSS

.list-group-item:hover {
  background: #fafafa;
  cursor: pointer;
}

JavaScript

JavaScript

  $('.list-group-item').on('click', function(){
    console.log('clicked item');
  });

  $('.remove-item').on('click', function(e){
    console.log('clicked remove-item btn');
    e.stopPropagation();
  });

UPDATE

更新

The problem seems to be that when hovering the inner X button, the mouse actually doesn't leave the 'list-group-item' element, thus, it keeps the hover state.

问题似乎是当悬停内部 X 按钮时,鼠标实际上并没有离开 'list-group-item' 元素,因此,它保持悬停状态。

I was able to solve it by manually dispatching mouseenterand mouseleaveon the 'list-group-item' in the mouseleaveand mouseenterevent of the 'remove-item' button, respectively, without the need to use 'event.stopPropagation()' (except for the button click handler).

我能够分别通过手动调度mouseentermouseleave在“删除项目”按钮的mouseleavemouseenter事件中的“列表组项目”来解决它,而无需使用“event.stopPropagation()”(除了按钮单击处理程序)。

The drawback is that I need a mouseenterand a mouseleaveevent handler for both elements. Preferably I'd use only CSS, but that seems to be impossible.

缺点是我需要一个mouseentermouseleave两个元素的事件处理程序。最好我只使用 CSS,但这似乎是不可能的。

I'm just not sure whether this is a clean solution, what do you think?

我只是不确定这是否是一个干净的解决方案,你怎么看?

Working sample here

工作样本在这里

CSS

CSS

.list-group-item.mouseover {
  background: #fafafa;
  cursor: pointer;
}

.list-group-item .remove-item.mouseover {
  background: #aaf;
  cursor: pointer;
}

JavaScript

JavaScript

  // LIST-ITEM EVENT HANDLERS

  $('.list-group-item').on('mouseenter', function(e){
    $(this).addClass('mouseover');
  }).on('mouseleave', function(e){
    $(this).removeClass('mouseover');
  });

  $('.list-group-item').on('click', function(){
    console.log('clicked item');
  });

  // LIST-ITEM REMOVE BUTTON EVENT HANDLERS

  $('.remove-item').on('mouseenter', function(e){
    $(this).addClass('mouseover');
    $(this).parent().mouseleave();
  }).on('mouseleave', function(e){
    $(this).removeClass('mouseover');
    $(this).parent().mouseenter();
  });

  $('.remove-item').on('click', function(e){
    console.log('clicked remove-item btn');
    e.stopPropagation();
  });

回答by Issam Zoli

This is impossible to do with CSS only, except the not-so-clean way described by @Pointy. You can do this with javascript by using event.stopPropagation(). So your hover style should become a class that you toggle on mouseover.

除了@Pointy 描述的不那么干净的方式之外,这仅用 CSS 是不可能的。您可以使用 javascript 执行此操作event.stopPropagation()。因此,您的悬停样式应该成为您在鼠标悬停时切换的类。

This question is a duplicate of css :hover only affect top div of nest

这个问题是css的重复:悬停只影响嵌套的顶部div

回答by Halcyon

You can make a negation caluse like Pointy suggests but a more solid solution involves adding an extra node. The idea is that the row and the button become proper siblings since you can't style a TextNode.

您可以像 Pointy 建议的那样进行否定计算,但更可靠的解决方案涉及添加额外的节点。这个想法是行和按钮成为正确的兄弟,因为你不能设置 TextNode 的样式。

<ul class="list-group">
  <li class="list-group-item">
    <div>Lalalalaiaia</div>
    <button class="btn btn-default btn-xs pull-right remove-item">
      <span class="glyphicon glyphicon-remove"></span>
    </button>
  </li>
  <li class="list-group-item">
    <div>Panananannaeue</div>
    <button class="btn btn-default btn-xs pull-right remove-item">
      <span class="glyphicon glyphicon-remove"></span>
    </button>
  </li>
</ul>

Now you can do:

现在你可以这样做:

.list-group-item div:hover {
  background: #fafafa;
  cursor: pointer;
}

You will need some extra trickery to get the button in the right place, like:

您需要一些额外的技巧才能将按钮放在正确的位置,例如:

// untested
.list-group-item {
  position: relative;
}
.list-group-item button {
  position: absolute;
  top: 5px;
  left: 5px;
}

回答by Reactgular

I could not find an answer that worked in all cases, and was also simple to implement. Sadly, there appears to be no consistent solution that is purely CSS and/or requires special arrangements of the HTML.

我找不到适用于所有情况且易于实施的答案。可悲的是,似乎没有一致的解决方案是纯粹的 CSS 和/或需要 HTML 的特殊安排。

Here is a jQuery solution that seems to work in all cases.

这是一个似乎适用于所有情况的 jQuery 解决方案。

Any element with .ui-hoverablewill receive a .ui-hoverclass that does not propagate. So you can stack .ui-hoverableelements and only the top-most under the mouse will have the .ui-hoverclass.

任何具有 的元素.ui-hoverable都将收到一个.ui-hover不会传播的类。因此,您可以堆叠.ui-hoverable元素,并且只有鼠标下方的最顶部才有.ui-hover该类。

$('.ui-hoverable').each(function() {
    var el = $(this);
    el.on('mousemove', function () {
        var parent = $(event.target).closest('.ui-hoverable');
        if(parent.length && parent[0] == el[0]) {
           el.addClass('ui-hover');
           return;
        }
        el.removeClass('ui-hover');
    });
    el.on('mouseleave', function () {
        el.removeClass('ui-hover');
    });
});

This works because the mousemoveevent searches for the closest .ui-hoverableand if it is not the current element the .ui-hoveris removed. So the top most will receive the .ui-hoverand an element under it will have it removed.

这是有效的,因为mousemove事件搜索最近.ui-hoverable的元素,如果它不是当前元素,则将.ui-hover其删除。所以最上面的将接收.ui-hover和它下面的元素将被删除。

Enjoy, report any problems.

享受,报告任何问题。

Thanks,

谢谢,