使用CSS在悬停时更改同级元素的颜色

77

在我的 HTML 代码中,当我悬停在 <a> 元素上时,我想仅使用 CSS 改变 <h1> 元素的颜色。是否有实现这一要求的方法?

<h1>Heading</h1>
<a class="button" href="#"></a>

如果我用一个带有id的div将它包裹起来呢?

<div id="banner">
    <h1>Heading</h1>
    <a class="button" href="#"></a>
</div>

这会有帮助吗?


除非您可以接受在悬停在div本身(而不是特定的锚点)时更改标题颜色,否则div将无法起到帮助作用。 - bfavaretto
11个回答

139
当你悬停在一个元素上时,你可以使其后面的同级元素发生变化,例如,当你悬停在h1标签上时,可以改变a链接的颜色,但是你不能以同样的方式影响前面的同级元素。请注意保留HTML标签。

h1 {
    color: #4fa04f;
}
h1 + a {
    color: #a04f4f;
}
h1:hover + a {
    color: #4f4fd0;
}
a:hover + h1 {
    background-color: #444;
}
<h1>Heading</h1>
<a class="button" href="#">The &quot;Button&quot;</a>
<h1>Another Heading</h1>

我们将H1的颜色设置为绿色,将A作为H1兄弟元素的颜色设置为红色(前两条规则)。第三条规则是描述如何在鼠标悬停在H1上时更改A的颜色。但请注意第四条规则“a:hover + h1”仅更改锚点后面的H1的背景颜色,而不是前面的H1。这基于DOM顺序,并且可以更改元素的显示顺序,因此即使无法更改先前的元素,也可以使该元素看起来在其他元素之后以获得所需的效果。请注意,这样做可能会影响可访问性,因为屏幕阅读器通常会按DOM顺序遍历项目,这可能与视觉顺序不同。

编辑

在支持它的浏览器中,现在可以使用has选择器进行编辑。
请参阅下面CSS中的注释。
我将来会再次编辑;目前我的Chrome和Safari浏览器还没有支持它的版本。

h1 {
    color: #4fa04f;
}
h1 + a {
    color: #a04f4f;
}
h1:hover + a {
    color: #4f4fd0;
}
a:hover + h1 {
    background-color: #444;
}
/* Select an H1 heading that has an <a>nchor as a sibling */
h1:has(+ a) {
    background-color: cyan;
}

/* Select an H1 heading that has a currently-hovered <a>nchor as a sibling */
h1:has(+ a:hover) {
    background-color: yellow;
}
<h1>Heading</h1>
<a class="button" href="#">The &quot;Button&quot;</a>
<h1>Another Heading</h1>


7
谢谢 Stephen,h1:hover + a 语法在 2020 年对我很有帮助 :)。 - Miguel Pereira

25

没有任何 CSS 选择器 可以做到这一点(即使在 CSS3 中)。在 CSS 中,元素永远不会意识到其父级,因此您不能使用 a:parent h1(例如)。它们也不知道它们的兄弟姐妹(在大多数情况下),因此您不能使用 #container a:hover { /* do something with sibling h1 */ }基本上,CSS 属性无法修改除了元素及其子元素以外的任何内容(它们无法访问父级或兄弟节点)。

您可以将 h1 放到 a 元素中,但这样会使您的 h1 也能被悬停。

您只能使用 JavaScript 来实现这一点(jsFiddle 概念验证)。这看起来可能是这样的:

$("a.button").hover(function() {
    $(this).siblings("h1").addClass("your_color_class");
}, function() {
    $(this).siblings("h1").removeClass("your_color_class");
});

我在看这个链接。你觉得它会起作用吗?http://net.tutsplus.com/tutorials/html-css-techniques/the-30-css-selectors-you-must-memorize/ - nasty
1
@Uds 抱歉,那些是标准的 CSS 选择器(我已经知道了),但它们中没有一个允许选择兄弟元素的父元素。(你可以使用“h1 + a”选择跟在'h1'后面的所有'a',但这不是你想要的。)基本上,CSS 属性只能修改一个元素或其子元素,而不能修改其兄弟元素或父元素。 - Cat
通用兄弟选择器 可以选择任何兄弟元素,但是选择器中的第一个元素必须在标记上出现在第二个元素之前(就像相邻兄弟选择器一样)。因此,两者都无法解决 OP 的问题,正如你所说的那样。 - bfavaretto
看起来我们对于父级选择器的期望很快就会得到满足,因为 level 4 subject selector 已经出现了。 - steveax
-1 是因为答案和评论都有错误: "Nor are they aware of their siblings" 是不正确的,需要进行编辑以修复(只要在HTML中指定了他们的兄弟姐妹,他们就知道自己的兄弟姐妹)。"You can do h1 + a to select all as which follow h1s" > 是不正确的,因为这是“相邻兄弟”选择器,而不是“一般兄弟”选择器。 - Laurent S.

10

#banner:hover h1 {
  color: red;
}

#banner h1:hover {
  color: black;
}

a {
  position: absolute;
}
<div id="banner">
  <h1>Heading</h1>
  <a class="button" href="#">link</a>
</div>

小提琴:http://jsfiddle.net/joplomacedo/77mqZ/ a元素是绝对定位的。可能不适合您现有的结构。让我知道,我可能会找到一个解决方法。

有点棘手!但还是很酷的。我能看出来它可能不适用于所有情况,但无论如何都很酷。 - Stephen P
尝试找出更好的方法。 ;) - João Paulo Macedo
2
这是一个不错的解决方案,但当div中不仅有h1a时会变得棘手。 - Cat
是的,但在这种情况下,div 只是用来帮助 - 至少从我理解问题的角度来看是这样。即使它不是一个解决方法,使用相同原则的替代方案也是完全可行的。 - João Paulo Macedo
但是使用JavaScript可能会更好。更易于理解-更直观,没有技巧。在CSS允许定位前面的兄弟元素之前,在这些情况下我可能会使用JavaScript。 - João Paulo Macedo
真是太棒了!五年后仍然有效。感谢这个启示 - 我用它来处理四列,在悬停时应该改变它们的宽度 - 它的效果非常好。 - tillinberlin

6

只需要几行CSS代码和基本的Flexbox理解,就可以实现这一点。

正如Stephen P在他的回答中所说的那样相邻兄弟组合器可以选择紧随其后的兄弟元素。要实现OP所要求的效果,可以使用两种Flex布局方法:

Approach 1 (using "flex-flow" shorthand property)

.flex-parent {
  display: flex;
  flex-flow: column-reverse wrap
}

.flex-child-1:hover + .flex-child-2 {
  color: #FF3333;
}
<div class="flex-parent">
    <a class="flex-child-1">Hover me</a>  
    <h1 class="flex-child-2">I am changing color</h1>
</div>

方法二(使用“order”属性和多个子元素

.flex-parent {
  display: flex;
  flex-direction: column;
}

.flex-child-1 {
  order: 2;
}

.flex-child-2 {
  order: 1;
}

.flex-child-3 {
  order: 3;
}

.flex-child-1:hover+.flex-child-2 {
  color: #FF3333;
}
<div class="flex-parent">
  <h1 class="flex-child-3">I am not changing color</h1>
  <a class="flex-child-1">Hover me</a>
  <h1 class="flex-child-2">I am changing color</h1>
</div>

奖励:

CodePen 奖励


4

http://plnkr.co/edit/j5kGIav1E1VMf87t9zjK?p=preview

<!DOCTYPE html>
<html>

  <head>
    <link rel="stylesheet" href="style.css">
    <script src="script.js"></script>
    <style>
      ul:hover > li
      {
        opacity: 0.5;
      }
      ul:hover li:hover 
      {
        opacity: 1;
      }
    </style>
  </head>

  <body>
    <h1>Hello Plunker!</h1>
    <ul>
      <li>Hello</li>
      <li>Hello</li>
      <li>Hello</li>
      <li>Hello</li>
      <li>Hello</li>
    </ul>
  </body>

</html>

这是一个纯CSS实现的例子,希望能帮助到某些人。

3

如果您悬停在父元素上但未悬停在子元素上,则此答案很好,但请注意所有子元素都会被悬停。 - martinedwards

1
将H1标签更改为链接,并将其样式与普通文本相同,然后使用此内容:
a:link {color:#FF0000;}      
a:hover {color:#FF00FF;}

当你悬停时,它应该可以工作 :) 你也可以通过将其包含在 div 中并像这样进行定位来使其更具体:

.exampledivname a:link {color:#FF0000;}      
.exampledivname a:hover {color:#FF00FF;}

这应该会有所帮助。


不行。我在同一個 div 裡面有更多的連結,所以我不能直接使用 a。 - nasty
刚刚意识到这不是你想要的。但它可能仍然有所帮助! - adamalexanderw

1

有人帮助了我,所以我想在这里分享。

在你的第一个例子中,使用纯CSS确实是不可能的。然而,当你将其包装在父容器中时,你就可以对悬停的子元素进行各种操作。

#banner:hover>h1{
  color:red;
}
h1:hover{
  color:black !important;
}
#banner{
  display:inline-block;
}
.button{
  display:inline-block;
  font-size:24px;
  width:100%;
  border:1px solid black;
  text-align:center;
}
h1{
  padding:0;
  margin:0;
}
<div id="banner">
    <h1>Heading</h1>
    <a class="button" href="#">Button!</a>
</div>

父元素只控制当前没有被悬停的子元素。然后,您可以设置单个元素和类的悬停状态,以便在没有JS的情况下进行兄弟选择。

以下是此操作的更高级示例

https://codepen.io/levyA/pen/gOrdaLJ


1
这是我实现的一个解决方案,用于实现附带的 .gif 动画中展示的行为。
CSS:
.features-container:has(.feature-card:hover) .feature-card {
    opacity: 0.25;
}

.feature-card:hover {
    opacity: 1 !important;
    transform: scale(105%);
    filter: drop-shadow(1px 1px 10px rgba(255, 255, 255, 0.25));
}

HTML:

<div class="features-container">
      <div
        onclick="window.location.href='/branding.html'"
        class="feature-card"
      >
        <img src="/assets/home-page/1_Tyson.jpg" alt="Mike Tyson Flexing" />
        <h2>Branding</h2>
      </div>

      <div
        onclick="window.location.href='/design.html'"
        class="feature-card"
      >
        <img
          src="/assets/home-page/2_Design.jpg"
          alt="Mike Tyson Flexing"
        />
        <h2>Design</h2>
      </div>
      <div
        onclick="window.location.href='/automotive.html'"
        class="feature-card"
      >
        <img
          src="/assets/home-page/3_Automotive.jpg"
          alt="Mike Tyson Flexing"
        />
        <h2>Automotive</h2>
      </div>
      <div onclick="window.location.href='/art.html'" class="feature-card">
        <img src="/assets/home-page/4_Art.jpg" alt="Mike Tyson Flexing" />
        <h2>Art</h2>
      </div>
      <div onclick="window.location.href='/more.html'" class="feature-card">
        <img
          src="/assets/home-page/5_Special_Services.jpg"
          alt="Mike Tyson Flexing"
        />
        <h2>More</h2>
      </div>
    </div>

简而言之,我们首先要确认我们的容器(在这种情况下是.features-container)是否有一个被悬停的元素。如果是这样,就降低.feature-card类的不透明度。
然而,由于CSS按顺序应用我们的规则,我们下一个规则将覆盖我们正在悬停的特定元素的0.25不透明度。注意:在这种特殊情况下,我们必须使用!important来覆盖先前设置的不透明度规则。
再次,请查看附带的.gif文件,这是一个很好的示例,展示了这里发生的情况。这当然可以通过JS来实现,但为什么要这样做,当CSS提供了一个更轻量级的解决方案呢? 悬停高亮示例

0

这个可能有效,我最近用过这个想法来停止动画中的兄弟元素。

h1 { color: inherit; }

#banner:hover { color: your choice; }
   

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