如何应用子元素的:hover效果而不影响父元素的:hover效果

12
使用以下HTML时,当我悬停在子元素上时,会在父元素上出现绿色背景。如何阻止这种情况发生?如果我在子元素之外悬停,我确实希望出现绿色背景。
CSS3可以使用。

.parent {
  padding: 100px;
  width: 400px;
  height: 400px;
}

.parent:hover {
  background-color: green;
}

.child {
  padding: 100px;
  width: 200px;
  height: 200px;
}

.child:hover {
  background-color: blue;
}
<div class="parent">
  <div class="child">Child</div>
</div>

6个回答

9

虽然这种方法真的很丑,但它能够发挥作用(一定程度上)。 我基本上将父元素复制为子元素的同级兄弟。 父元素自始默认隐藏,然后在鼠标悬停于子元素上时显示。 Chrome不喜欢它,除非您使用+选择器而不是~选择器。 这并不是非常可扩展的,但它可能有效。

正如其他人所发布的,javascript可能是更好的解决方案。

 <style>
  .parent { padding: 100px; width: 400px; height:400px; position: relative; z-index: 998; }
  .parent:hover { background-color: green; }
  .child { padding: 100px; width: 200px; height:200px; position: relative; z-index: 1000; }
  .child:hover { background-color: blue; }
  .parent-overwrite { padding: inherit; width: inherit; height: inherit; position: absolute; top: 0; left: 0; z-index: 999; background-color: #FFF; display: none; }
  .child:hover ~ .parent-overwrite { display: block; }
</style>

<div class="parent">
    <div class="child">Child</div>
    <div class="parent-overwrite"></div>
</div>


1
谢谢你的尝试 :) 但是,由于可扩展性的原因,这对我是行不通的。 - case nelson
2
哈哈哈,谢谢,这是一个有趣的问题要解决。我之前也遇到过完全相同的问题,但我认为我的解决方案是手动更改没有悬停声明的父类的类。但这对你来说行不通,因为你仍然希望在父类上悬停。我的程序员认为我会因为这个丑陋的 hack 而受到严重的负面评价。谢谢你证明了他的错误 ;) - Bryan Downing

9

2022年:

现在可以通过以下表达式结合 :has:not 伪类来实现:

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

简单来说:

.parent
  /* When this element is hovered */
  :hover 
  /* but it does not */
  :not(
    /* have a child node .child, that is also hovered */
    :has(.child:hover)
  ) {
  /* apply these rules */
}

下面是原始片段的可用修改版本:

.parent {
  padding: 100px;
  width: 400px;
  height: 400px;
}

.parent:hover:not(:has(.child:hover)) {
  background-color: green;
}

.child {
  padding: 100px;
  width: 200px;
  height: 200px;
}

.child:hover {
  background-color: blue;
}
<div class="parent">
  <div class="child">Child</div>
</div>

通过将.child选择器替换为.parent选择器,可以实现递归。

浏览器支持情况请查看此处。撰写本文时,所有主流浏览器均支持该功能,除了Firefox仍然存在缺陷的实验性实现。


有多个条件是可能的吗?我无法通过.parent:hover:not(:has(.child1:hover, .child2:hover)).parent:hover:not(:has(.child1:hover):has(.child2:hover)).parent:hover:not(:has(.child1:hover)):not(:has(.child2:hover))获得结果。 - vatavale
1
@vatavale 你可以在 :where 中包装您的“条件”。Stackoverflow 评论不能很好地显示代码块,但这里有一个演示沙盒:https://codepen.io/Mest/pen/jOKqPzm - Nils Kaspersson
太棒了!如此干净和精确。谢谢! - JBrown
您还可以使用.parent:hover:not(:has(*:hover)) { ... }来禁用所有子元素的悬停效果。 - Zach Saucier

3

我只能通过添加额外的标记来实现这个功能。需要添加一个空的 div,它实际上充当父背景。请查看此处的 CSS。

HTML 部分

  <div class="parent">
    Parent
    <div class="child">
      Child
      <div class="grandson">
        Grandson
        <div class="grandson-bg"></div>
      </div>
      <div class="child-bg"></div>
    </div>
    <div class="parent-bg"></div>
  </div>

CSS部分:

article, aside, figure, footer, header, hgroup, menu, nav, section { display: block; }

  .parent { display: block; position: relative; z-index: 0;
            height: auto; width: auto; padding: 25px;
          }

  .parent-bg { display: block; height: 100%; width: 100%; 
               position: absolute; top: 0px; left: 0px; 
               border: 1px solid white; z-index: 0; 
             }
  .parent-bg:hover { border: 1px solid red; }

  .child { display: block; position: relative; z-index: 1; 
           height: auto; width: auto; padding: 25px;
         }

  .child-bg { display: block; height: 100%; width: 100%; 
              position: absolute; top: 0px; left: 0px; 
              border: 1px solid white; z-index: 0; 
            }
  .child-bg:hover { border: 1px solid red; }

  .grandson { display: block; position: relative; z-index: 2; 
              height: auto; width: auto; padding: 25px;
            }

  .grandson-bg { display: block; height: 100%; width: 100%; 
                 position: absolute; top: 0px; left: 0px; 
                 border: 1px solid white; z-index: 0; 
               }
  .grandson-bg:hover { border: 1px solid red; }

http://jsbin.com/ubiyo3/edit


1

在这种情况下,最简单的方法可能是使用JS来处理CSS。也许你可以重新考虑你的实现方式。为什么要尝试做这样的事情呢?


我有一个很大的元素树,其中一些元素会响应鼠标点击。我只想突出显示将响应点击的元素。在Javascript中实现这个效果意味着基于mouseover/mouseout进行样式设计,这将使代码库变得更加臃肿。 - case nelson
1
它不会使代码库臃肿 - 如果您正在使用jQuery,它将只需要大约4-5行代码。伪代码如下:$('.parent').hover(function(){ ...设置CSS为绿色...}); $('.child').hover(function(){ this.parent.css(..设置CSS为白色..}); - Tilo Mitra

1

使用普通的 CSS 是不可能实现这个的。你要求一个子元素的伪类 (child:hover) 影响父元素的 background 声明,但是没有办法使用常规的 CSS 来指定这种情况。

使用 JavaScript 绝对可以实现。


我并不认为这不能用CSS完成。 我想以某种方式更改.parent:hover,只有在没有子元素悬停时才进行选择。这样子元素就不会影响父级声明,而父级选择器会更加明智。 - case nelson
不行,这正是CSS设计师们排除的内容。编写、规范和使用那种模型几乎是不可能的。在XPATH中,可以使用父选择器,但没有伪元素和类需要担心。对于他们来说,这是一个艰难的决定,但你不能使用CSS允许子选择器过滤回影响父级。 - Nicholas Wilson

0

我认为我有一个更好的解决方案,因为它可以扩展到更多级别,任意数量的级别,而不仅仅是两个或三个。

我使用边框,但也可以使用任何想要的样式,比如背景颜色。

通过边框,我的想法是:

  • 只在一个div上有不同的边框颜色,即鼠标所在的div上,不在任何父元素上,也不在任何子元素上,因此只能看到这样的div边框以不同的颜色显示,而其余部分保持白色。

您可以在以下链接进行测试:http://jsbin.com/ubiyo3/13

这是代码:

<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>Hierarchie Borders MarkUp</title>
<style>

  .parent { display: block; position: relative; z-index: 0;
            height: auto; width: auto; padding: 25px;
          }

  .parent-bg { display: block; height: 100%; width: 100%; 
               position: absolute; top: 0px; left: 0px; 
               border: 1px solid white; z-index: 0; 
             }
  .parent-bg:hover { border: 1px solid red; }

  .child { display: block; position: relative; z-index: 1; 
           height: auto; width: auto; padding: 25px;
         }

  .child-bg { display: block; height: 100%; width: 100%; 
              position: absolute; top: 0px; left: 0px; 
              border: 1px solid white; z-index: 0; 
            }
  .child-bg:hover { border: 1px solid red; }

  .grandson { display: block; position: relative; z-index: 2; 
              height: auto; width: auto; padding: 25px;
            }

  .grandson-bg { display: block; height: 100%; width: 100%; 
                 position: absolute; top: 0px; left: 0px; 
                 border: 1px solid white; z-index: 0; 
               }
  .grandson-bg:hover { border: 1px solid red; }

</style>
</head>
<body>
  <div class="parent">
    Parent
    <div class="child">
      Child
      <div class="grandson">
        Grandson
        <div class="grandson-bg"></div>
      </div>
      <div class="child-bg"></div>
    </div>
    <div class="parent-bg"></div>
  </div>
</body>
</html>

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