防止CSS:悬停样式传播

问题描述 投票:0回答:4

在下面的示例中,当我将鼠标悬停在“X”按钮上时,列表项

hover
样式也会启用,我不希望发生这种情况。

按钮上是否可以有

hover
样式,独立于
hover
上的
list-group-item
样式?诸如阻止“悬停”传播之类的东西?

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

工作示例在这里

<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

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

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();
  });

更新

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

我可以通过在“删除项目”按钮的

mouseenter
mouseleave
事件中分别在“列表组项目”上手动调度
mouseleave
mouseenter
来解决这个问题,而不需要使用“event.stopPropagation()”(按钮单击处理程序除外)。

缺点是我需要两个元素的

mouseenter
mouseleave
事件处理程序。我最好只使用 CSS,但这似乎是不可能的。

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

工作示例在这里

CSS

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

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

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();
  });
javascript jquery html css mouseover
4个回答
6
投票

仅使用 CSS 是不可能做到这一点的,除了 @Pointy 描述的不太干净的方式。 您可以使用

event.stopPropagation()
使用 javascript 来完成此操作。因此,您的悬停样式应该成为您在鼠标悬停时切换的类。

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


6
投票

好吧,实际上有一个只需要使用 CSS 的解决方案(不需要 HTML 或 JS 的东西)

以下选择器将仅选择悬停时具有“parent”类的元素,这些元素没有悬停在其上的“child”类的子元素。

.parent:has(:not(.child:hover)):hover {}

我能看到的

:has()
选择器/伪类的唯一问题是浏览器支持(尤其是旧版本) - 所以在使用它之前,请检查当前的兼容性列表,看看它是否符合您的要求。

编辑:

提供的解决方案似乎不适用于某些人/浏览器版本。另一种选择(由 Eric 在评论中提供)是

.parent:not(:has(.child:hover)):hover
。 (我不确定为什么这两种解决方案对某些浏览器的工作方式不同 - 因为两者的逻辑是相同的) - Chrome v122 都对我有用 / Chrome v124 对 Chris Hayes 只有第二个有效


3
投票

您可以像 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>

现在你可以做:

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

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

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

2
投票

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

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

任何具有

.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');
    });
});

这是有效的,因为

mousemove
事件会搜索最近的
.ui-hoverable
,如果它不是当前元素,则
.ui-hover
将被删除。因此,最顶部的元素将收到
.ui-hover
,而其下方的元素将被删除。

享受,报告任何问题。

谢谢,

© www.soinside.com 2019 - 2024. All rights reserved.