CSS 根据邻接元素和特定的子元素选择元素[重复]。

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

这是一个简化的网页结构。

<div>
    <div>div 1</div>
    <div>div 2<a href="/foo">foo</a></div>
    <p>select me</p>
    <p>keep me alone</p>
</div>

我想选择所有 p 凭藉 diva 里面。这是我最好的尝试。

document.querySelectorAll('(div > a[href="/foo"]) ~ p')

但显然这不是一个虚拟的CSS选择器。

是否可以选择 p 如果它有邻居 diva 内?

html css css-selectors
1个回答
2
投票

是否可以选择p,如果它有一个内嵌的邻接div?

你需要使用 :has() 选择器,但是完整的解决方案取决于你是否要在 实时资料 "或 "快照资料":

负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 实况转播 适合在任何情况下使用,包括浏览器CSS选择器匹配,这是实时的。它包括本文档中定义的所有选择器,除了 :has():

负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 负责人: 快照资料 适用于对性能不是非常敏感的上下文;特别是适用于根据静态文档树评估选择器的上下文。例如 querySelector() 方法应该使用DOM中定义的快照配置文件。

当谈到 :has() 特别是。

  • .css<style> 样式表规则选择器(这是一个活的上下文)。没有.
  • .css<style> 样式表规则选择器,并使用客户端脚本,允许使用 :has() 这意味着它实际上是使用了快照上下文)。是的
  • querySelector, querySelectorAll, matches 和其他DOM函数(这是一个快照上下文)。是的
    • 但从2020年5月起,没有任何浏览器原生支持使用。:has() 在这些函数中。
    • 在粗略地搜索了一下之后,我找不到一个 polyfill 或补丁来添加对 :has() 对于 querySelector 等,嘘!

但假设你能用 :has() (例如:因为你是在2030年看这篇文章),那么这个查询就可以了。

div:has(> a[href="/foo"]) ~ p

为什么不是... :has() 中的元素?

有很多原因导致CSS不支持根据其子元素来选择元素(尽管有少数例外,如 :empty:focus-within),但主要原因是。

  • 这将使CSS选择器的评估计算成本更高。
  • CSS被设计成与部分加载的文档一起工作,这样当文档被加载时,它就不会彻底改变外观。

作为一个思想实验:假设浏览器确实能够支持 :has() 在CSS样式规则中,考虑一个像这样的HTML文档。

<html>
<head>
    <style>
    p { background-color: red; }
    p:has(div) { background-color: blue; }
    </style>
</head>
<body>
    <p>foo <div></div></p>
    <p>bar</p>
    <p>baz <div></div></p>
</body>
</html>

"foo "和 "baz "元素是蓝色的 "bar "元素是红色的。

现在,如果浏览器的这个文档处于部分加载的状态,以至于它到目前为止只加载了这个(在用户的Wi-Fi连接死机之前)--或者在下一个TCP数据包到达之前。

<html>
<head>
    <style>
    p { background-color: red; }
    p:has(div) { background-color: blue; }
    </style>
</head>
<body>
    <p>foo

浏览器需要通过为被截断的元素插入自己的关闭标记来干净地终止一个部分加载的文档,就像这样。

<html>
<head>
    <style>
    p { background-color: red; }
    p:has(div) { background-color: blue; }
    </style>
</head>
<body>
    <p>foo</p>
</body>
</html>

所以,当文档处于这种状态时,第一句话 p 将会是红色的,而不是蓝色的--那么在用户的Wi-Fi连接重新连接后(或者下一个TCP数据包到达后),页面完成下载,那么... ... <p>foo</p> 赢得 <div> 于是 :has(div) 现在适用该规则,并且 <p>foo</p> 会突然由红变蓝 - 这可不是什么好事。

在这个人为的例子中,像背景色的改变这样的微不足道的差异并不重要--但是,如果这个 :has() 选择器被用来控制页面布局的一些重大差异(如 body:has(footer) > main { display: grid;),那么当页面还在加载的时候,就会把页面布局搞得一团糟--这就是为什么基于子代内容的选择器在目前的形式下将不被支持。

(但是考虑到子代选择器的实用性和效用,我想它们会在将来被重新引入,并以某种方式限制规则只在以下情况下使用 DOMContentLoaded 当选择器不确定的时候,已经启动或需要一个默认或回退。


0
投票

我可能没有正确理解你的问题,但是如果你想只选择 <p>select me</p>,为什么不能直接把它分配给一个班级呢?

例如:

HTML:

<div>
    <div>div 1</div>
    <div>div 2<a href="/foo">foo</a></div>
    <p class="selected">select me</p>
    <p>keep me alone</p>
</div>

CSS。

.selected {
color: green;
}


-1
投票

就目前而言(据我所知),你不能在CSS中从一个子代中选择一个父代,更不用说和相邻的 "父代 "了。 不过我给你的最佳答案是这样的,希望能帮到你。

div + p {
  background-color: yellow;
}
<div>
    <div>div 1</div>
    <div>div 2<a href="/foo">foo</a></div>
    <p>select me</p>
    <p>keep me alone</p>
</div>
© www.soinside.com 2019 - 2024. All rights reserved.