当鼠标悬停在一个元素上时如何影响其他元素。

709
我想要做的是当一个特定的
被悬停时,它会影响另一个
的属性。

例如,在这个JSFiddle演示中,当你悬停在#cube上时,它会改变background-color,但我想要的是当我悬停在#container上时,#cube会受到影响。

div {
  outline: 1px solid red;
}

#container {
  width: 200px;
  height: 30px;
}

#cube {
  width: 30px;
  height: 100%;
  background-color: red;
}

#cube:hover {
  width: 30px;
  height: 100%;
  background-color: blue;
}
<div id="container">
  <div id="cube">
  </div>
</div>

9个回答

1534

如果立方体直接在容器内部:

#container:hover > #cube { background-color: yellow; }

如果cube紧随(在容器的结束标签之后)容器之后:

#container:hover + #cube { background-color: yellow; }
如果立方体在容器内:
#container:hover #cube { background-color: yellow; }
如果立方体是容器的兄弟节点:
#container:hover ~ #cube { background-color: yellow; }

142
不要忘记使用一般兄弟选择器~,表示“立方体在容器后面且它们有共同的父级元素” 。 - robertc
4
很不错。是否有可以找到更多相关信息的来源?它被所有浏览器支持吗?是CSS3吗?能否提供更多信息将是很棒的。非常感谢! - Anonymous
7
+1 @Mike 的回答很棒。如果 #container 紧挨着 #cube,也就是说 #container 接在 #cube 后面,那会怎样呢? - PeterKA
9
如果悬停元素位于我们想要影响的容器内,该怎么办? 例如:#cube:hover #container{一些CSS效果} - Hanzallah Afgan
4
好的回答!那么如果我希望在鼠标悬停在子元素上时更改其父元素,该怎么办呢?我认为没有适用于此情况的选择器。 - Mikel
显示剩余14条评论

57

在这个特定的例子中,你可以使用:

#container:hover #cube {
    background-color: yellow;   
}

这个示例仅适用于cubecontainer的子元素。对于更复杂的情况,您需要使用不同的CSS或使用JavaScript。


53
使用兄弟选择器是在鼠标悬停在某个元素上时样式化其他元素的通用解决方案,但前提是其他元素在DOM中跟随该元素。如果其他元素实际上应该在悬停元素之前呢?假设我们想要实现一个信号条评分小部件,就像下面这个例子:

Signal bar rating widget

用 CSS flexbox 模型可以轻松实现此功能,只需将 flex-direction 设置为 reverse 即可,这样元素就会以与 DOM 中的顺序相反的顺序显示。上面的截图是使用纯 CSS 实现的小部件。 Flexbox 得到 95% 现代浏览器的很好支持。

.rating {
  display: flex;
  flex-direction: row-reverse;
  width: 9rem;
}
.rating div {
  flex: 1;
  align-self: flex-end;
  background-color: black;
  border: 0.1rem solid white;
}
.rating div:hover {
  background-color: lightblue;
}
.rating div[data-rating="1"] {
  height: 5rem;
}
.rating div[data-rating="2"] {
  height: 4rem;
}
.rating div[data-rating="3"] {
  height: 3rem;
}
.rating div[data-rating="4"] {
  height: 2rem;
}
.rating div[data-rating="5"] {
  height: 1rem;
}
.rating div:hover ~ div {
  background-color: lightblue;
}
<div class="rating">
  <div data-rating="1"></div>
  <div data-rating="2"></div>
  <div data-rating="3"></div>
  <div data-rating="4"></div>
  <div data-rating="5"></div>
</div>


这个能不能编辑一下,让高亮不会在从一个条形图移到另一个时消失?闪烁有点分散注意力。 - Cerbrus
@Cerbrus:添加了一种解决方案,不会在鼠标位于两个条之间时隐藏悬停。缺点是条的宽度不再相等。 - Dan Dascalescu
1
在你的第一个片段中尝试这个:对于 .rating div,移除边距,并添加 border-right: 4px solid white; - Cerbrus
1
Flex方向(在IE上支持不好)或者1)默认为黑色 2)当鼠标悬停在容器上时,全部变为蓝色 3)当鼠标悬停在bar上时,下一个兄弟元素变为黑色 :) - Stephane Mathis
1
我创建了这个 JSFiddle,它(至少对我来说)让这里正在发生的事情更加明显。https://jsfiddle.net/maxshuty/cj55y33p/3/ - maxshuty
1
这是个好主意!对于只需要一个元素来触发DOM中的悬停效果的情况,我认为最好使用flexbox的order属性,这样如果只有一个元素需要触发悬停效果,就不必维护整个列表的反向顺序。 - TimE

19

只有这个方法对我有用:

#container:hover .cube { background-color: yellow; }

.cube 是在 #container 内部的 CssClass。

FirefoxChromeEdge 浏览器中测试过。


10
这里有另一个想法,可以通过使用主元素的:hover状态而不考虑任何特定选择器来影响其他元素。
为此,我将依赖于使用自定义属性(CSS变量)。正如我们可以在规范中所读到的:
引用:

自定义属性是普通属性,因此它们可以在任何元素上声明,并且使用普通继承和级联规则进行解析...

这个想法是在主元素内定义自定义属性并使用它们来样式化子元素,由于这些属性是继承的,因此我们只需要在悬停时在主元素内更改它们。
下面是一个例子:

#container {
  width: 200px;
  height: 30px;
  border: 1px solid var(--c);
  --c:red;
}
#container:hover {
  --c:blue;
}
#container > div {
  width: 30px;
  height: 100%;
  background-color: var(--c);
}
<div id="container">
  <div>
  </div>
</div>

这种方法为什么比使用具体选择器与悬停结合更好? 我可以提供至少两个原因,使此方法成为考虑的好方法:
  1. 如果我们有许多嵌套元素共享相同的样式,这将避免我们使用复杂的选择器在悬停时定位所有元素。使用自定义属性,我们仅在父元素上悬停时更改属性值。
  2. 自定义属性可用于替换任何属性的值,也可以替换部分属性值。例如,我们可以为颜色定义自定义属性,并在borderlinear-gradientbackground-colorbox-shadow等中使用它。这将避免我们在悬停时重置所有这些属性。
下面是一个更复杂的例子:

.container {
  --c:red;
  width:400px;
  display:flex;
  border:1px solid var(--c);
  justify-content:space-between;
  padding:5px;
  background:linear-gradient(var(--c),var(--c)) 0 50%/100% 3px no-repeat;
}
.box {
  width:30%;
  background:var(--c);
  box-shadow:0px 0px 5px var(--c);
  position:relative;
}
.box:before {
  content:"A";
  display:block;
  width:15px;
  margin:0 auto;
  height:100%;
  color:var(--c);
  background:#fff;
}

/*Hover*/
.container:hover {
  --c:blue;
}
<div class="container">
<div class="box"></div>
<div class="box"></div>
</div>

如上所述,我们只需要一个CSS声明就可以改变不同元素的许多属性。


10

除了其他答案中已经提供的常见选择器外,现在你可以依赖于 :has() 来解决没有父/子或兄弟关系的情况。

以下是一个示例:

.box {
  width: 200px;
  aspect-ratio: 1;
  display: inline-block;
  border: 1px solid red;
}

.box > div {
  margin: 5px;
  height: 100%;
  border: 2px solid green;
  cursor: pointer;
}
/* when div1 is hovered make div2 blue */
body:has(#div1:hover) #div2 {
  background: blue;
}
/* when div2 is hovered make div1 purple */
body:has(#div2:hover) #div1 {
  background: purple;
}
<div class="box">
  <div id="div1">
  </div>
</div>

<div class="box">
  <div id="div2">
  </div>
</div>

如您所见,我们可以通过将光标悬停在div2上来影响div1,反之亦然。


1
注意:用户必须明确将 layout.css.has-selector.enabled 首选项设置为 true,才能在 Firefox 中使用此功能。 - Abdul Aziz Barkat

9

非常感谢Mike和Robertc的有用帖子!

如果您的HTML中有两个元素,并且您想要在一个元素上进行:hover并针对另一个元素进行样式更改,则这两个元素必须直接相关-父项、子项或同级项。这意味着这两个元素必须要么一个在另一个内部,要么都包含在同一个较大的元素中。

我想在用户阅读我的网站时,在浏览器右侧显示定义框,并在高亮词上进行:hover; 因此,我不希望“定义”元素显示在“文本”元素内。

我差点放弃了,只是在我的页面上添加了JavaScript,但这是未来的趋势!我们不应该忍受CSS和HTML的反向说法,告诉我们必须将元素放置在哪里才能实现我们想要的效果!最终,我们妥协了。

虽然文件中的实际HTML元素必须嵌套或包含在单个元素中,以成为彼此有效的:hover目标,但可以使用css position属性将任何元素显示在所需位置。我使用了position:fixed将我的:hover操作的目标放置在用户屏幕上我想要的位置,而不管它在HTML文档中的位置。

HTML代码:

<div id="explainBox" class="explainBox"> /*Common parent*/

  <a class="defP" id="light" href="http://en.wikipedia.or/wiki/Light">Light                            /*highlighted term in text*/
  </a> is as ubiquitous as it is mysterious. /*plain text*/

  <div id="definitions"> /*Container for :hover-displayed definitions*/
    <p class="def" id="light"> /*example definition entry*/ Light:
      <br/>Short Answer: The type of energy you see
    </p>
  </div>

</div>

样式表:

/*read: "when user hovers over #light somewhere inside #explainBox
    set display to inline-block for #light directly inside of #definitions.*/

#explainBox #light:hover~#definitions>#light {
  display: inline-block;
}
    
.def {
  display: none;
}
    
#definitions {
  background-color: black;
  position: fixed;
  /*position attribute*/
  top: 5em;
  /*position attribute*/
  right: 2em;
  /*position attribute*/
  width: 20em;
  height: 30em;
  border: 1px solid orange;
  border-radius: 12px;
  padding: 10px;
}

在这个例子中,来自于#explainBox内部元素的:hover命令的目标必须是#explainBox或者在#explainBox内部。为了让#definitions出现在期望的位置(在#explainBox外面),已经分配了位置属性,即使它在HTML文档中实际上处于一个不想要的位置。
我知道在多个HTML元素中使用相同的#id被认为是不好的做法;然而,在这种情况下,由于它们分别位于唯一的#id元素中,可以独立地描述#light的各个实例。在这种情况下重复id#light有没有什么理由不这样做?

虽然这只是一个简短的观点,但是下面是一个jsfiddle链接,其中包含了详细的答案:http://jsfiddle.net/ubershmekel/bWgq6/1/ - ubershmekel
2
一些浏览器在多次使用相同的“ID”时会出现问题。只需使用“class”。 - Serj Sagan

3

警告:如果您能够使用 CSS,请使用 CSS 而不要使用 JavaScript!

如果您想选择一个位置未知或不可达的元素,则可以使用 JavaScript。

const cube = document.getElementById('cube')
const container = document.getElementById('container')

cube.addEventListener('mouseover', () => container.style.backgroundColor = "blue")
cube.addEventListener('mouseleave', () => container.style.backgroundColor = "white")
div {
  outline: 1px solid red;
  width: 200px;
  height: 30px;
}

#cube {
  background-color: red;
}
<main>
  <div id="container">
  </div>
</main>
<div id="cube">
</div>


1
#imageDiv:hover  #detailDiv
{
    z-index: -999 !important;
}

这里

#imageDiv 是第一个需要悬停的 div

#detailDiv 是第二个在悬停时应用css样式的 div

因此,如果我悬停在第一个 div 上,那么 zindex 将被分配给第二个 div

对我有用


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