【问题标题】:Apply styles to nested child using CSS descendant combinator with pseudo-class使用带有伪类的 CSS 后代组合器将样式应用于嵌套子级
【发布时间】:2021-07-16 07:21:38
【问题描述】:

我们如何将样式应用于父元素 (P) 的子元素 (C),同时在出现伪类状态时使用后代组合器指定它们的关系?

一个小场景是,当.menu-item 悬停在上面时,父元素.menu-item 的子元素a 需要改变颜色。这在下面给出的代码中表示:

.menu {
  list-style-type: none;
}
.menu-item {
  padding: 0.5rem;
}
.menu-item a {
  text-decoration: none;
  color: #222;
}
.menu-item:hover .menu-item a {
  color: #a2b;
}
<ul class="menu">
  <li class="menu-item">
    <a href="#" class="menu-link">Home</a>
  </li>
  <li class="menu-item">
    <a href="#" class="menu-link">About</a>
  </li>        
  <li class="menu-item">
    <a href="#" class="menu-link">Contact</a>
  </li>
</ul>

但是,当以下代码 sn-p 没有明确指定 a 是 .menu-item 的子代时,它可以工作:

.menu-item:hover a {
  color: #a2b;
}

在明确指定元素之间的关系的同时,还有其他方法可以在 CSS 中实现这一点吗?

【问题讨论】:

    标签: html css css-selectors


    【解决方案1】:

    在明确指定元素之间的关系的同时,还有其他方法可以在 CSS 中实现这一点吗?

    你已经是了,使用后代组合器。

    组合子表示两个元素之间的关系,每个元素都由一个复合选择器表示。复合选择器由一个或多个简单选择器组成,all 代表元素状态的某些方面。选择器不需要你分离一个元素的状态,以及同一个元素与另一个元素的关系。这既对其优雅有效,但也对其不利,因为它产生了许多限制,例如无法从后代遍历到其祖先,从后来的兄弟姐妹到其先前的兄弟姐妹等等。但这是一个单独的问题。

    在选择器.menu-item:hover a 中,有两个复合选择器:.menu-item:hover 和a。三个简单选择器中的每一个都代表一个特定的状态,但其中两个通过出现在单个复合选择器中来应用于同一个元素。在这种情况下,:hover 伪类表示它代表.menu-item,尽管只是在它处于悬停状态时。

    这并不意味着或暗示a 仅在处于悬停状态时从.menu-item 下降。相反,这意味着a 元素仅在它来自至少一个匹配.menu-item:hover 的元素(换句话说:具有至少一个祖先)时才会匹配。事实上,如果您将.menu-item:hover 更改为:hover.menu-item,它仍然会匹配,因为复合选择器中的类和伪类之间的顺序无关紧要,它们是平等的。然后,您也可以将其视为“明确表示a 是处于悬停状态的元素的后代”,并尝试编写类似:hover.menu-item :hover a 的内容,但这显然也不起作用。这可能有助于您理解为什么已经通过使用后代组合器本身明确指定了关系。

    因此,选择器.menu-item:hover a(以及,扩展为:hover.menu-item a)意味着

    将此规则应用于任何 a 元素
    继承自(或:有一个祖先)处于 :hover 状态的 .menu-item 元素。

    而且,由于在使用后代组合器时已经明确指定了关系,因此选择器 .menu-item:hover .menu-item a 与 两个 后代组合器意味着

    将此规则应用于任何 a 元素
    继承自 .menu-item 元素
    它本身是 另一个 .menu-item 元素的后代,一个处于 :hover 状态的元素。

    这就是它不起作用的原因。此外,正如 A Haworth 所说,由于您的标记中没有任何嵌套的 .menu-items,因此它根本不会匹配任何 a 元素。

    要更深入地解释组合器和元素状态如何在选择器中工作,请参阅我对这个问题的回答:

    ↪How do I select an element based on the state of another element in the page with CSS?

    【讨论】:

    • 您的回答不仅是答案,而且是有启发性的文章!
    • @Srishti:谢谢!如果您想知道,有人标记了您的原始评论,另一位版主将其删除,因为 Stack Overflow 尽量不保留这些类型的 cmets。但我确实很感激,而且我对它一开始就被删除并不感到特别高兴。
    【解决方案2】:

    你说:

    但是,当下面的代码 sn-p 没有被编写时,它可以工作 明确指定 a 是 .menu-item 的子项:

    .menu-item:hover a { color: #a2b; }

    确实,该代码没有明确指定 a 是 .menu-item 的子项。它在说什么

    '这是任何作为悬停的后代的 a 的颜色 菜单项'

    在您的情况下,这就是您想要的,因为锚元素中不会有其他嵌套的锚元素,因此您只更改一个的颜色。

    这可能是一种更容易维护的表达要求的方式,而不是绝对要求 a 是菜单项的子项(而不是任何后代),因为如果稍后有人将锚元素放在 div 中,例如你当菜单项悬停时,仍然希望颜色发生变化。

    问题中给出的其他代码:

    .menu-item:hover .menu-item a {
      color: #a2b;
    }
    

    在说

    当一个菜单项被悬停时,寻找它所有的菜单项后代和 为它们的任何锚元素后代着色。

    嵌套菜单项不是您所拥有的结构,因此悬停的菜单项不会发生任何事情。

    【讨论】:

      【解决方案3】:

      我会直接使用a:hover,除非您希望整个menu-item div 在悬停时改变颜色

      a:hover {
        color: #a2b;
      }
      

      <ul class="menu">
        <li class="menu-item">
          <a href="#" class="menu-link">Home</a>
        </li>
        <li class="menu-item">
          <a href="#" class="menu-link">About</a>
        </li>        
        <li class="menu-item">
          <a href="#" class="menu-link">Contact</a>
        </li>
      </ul>
      
      .menu {
        list-style-type: none;
      }
      .menu-item {
        padding: 0.5rem;
      }
      .menu-item {
        text-decoration: none;
        color: #222;
      }
      a:hover {
        color: #a2b;
      }
      

      .menu-item:hover .menu-item a { color: #a2b; } 不起作用的原因是因为层次结构是 menu > menu-item > a:hover

      【讨论】:

        猜你喜欢
        • 2020-11-04
        • 2020-04-17
        • 2016-05-06
        • 1970-01-01
        • 2016-03-03
        • 2016-08-11
        • 2022-07-20
        • 2021-06-25
        • 2021-09-01
        相关资源
        最近更新 更多