:has vs:matches - 选择器等级4

ale*_*ers 4 css css-selectors

只是想知道CSS(选择器4)伪选择器:has和.之间的区别是什么:matches

规范http://dev.w3.org/csswg/selectors-4/#overview说:

E:匹配(s1,s2)
与复合选择器s1和/或复合选择器s2匹配的E元素
§4.2匹配 - 任何伪类:: matches()

E:(rs1,rs2)
是一个E元素,如果相对选择器rs1或rs2中的任何一个,当用E作为:scope元素进行求值时,匹配一个元素
§4.4TheRelational Pseudo-class :: has()

Bol*_*ock 9

简而言之:

  • E:has(rs1, rs2)匹配Ë当不同的元件F匹配任意的选择参数相至E.如果你知道jQuery的:has()选择器,那就完全一样了.

  • E:matches(s1, s2)E本身匹配任何选择器参数时匹配E. 可以认为是:matches()直接相反的:not(),如果E本身与任何参数都不匹配,则与E匹配.1您也可以将其:matches()视为jQuery .filter()方法的伪类版本.

    这种表示法等同于将每个选择器参数与E连接(假设您实际上可以连接它们),这样您就有了一个选择器列表(E)(s1), (E)(s2).例如,div:matches(.foo, .bar)相当于div.foo, div.bar.

这根本的区别是展现得直截了当与选择div:matches(p)div:has(p):

  • div:has(p)匹配任何div该元素具有一个p后代.这是非常相似的div p,除了前者的目标div ,后者的目标是p.

  • 因为一个div永远不会一个p,div:matches(p)永远不会匹配任何东西.(同样,div:not(p)将匹配所有div元素.)


这是一个更复杂的例子,略微不那么荒谬的选择器:

div:has(.foo, .bar)
div:matches(.foo, .bar)
Run Code Online (Sandbox Code Playgroud)

使用以下标记:

<div class="foo"></div> <!-- [1] -->
<div class="bar"></div> <!-- [1] -->

<div class="foo bar">   <!-- [2] -->
  <p></p>
</div>

<div>                   <!-- [3] -->
  <p class="foo"></p>
</div>

<div>                   <!-- [3] -->
  <div>                 <!-- [3] -->
    <p class="bar"></p>
  </div>
</div>

<div>                   <!-- [4] -->
  <div class="foo">     <!-- [5] -->
    <p class="bar"></p>
  </div>
</div>
Run Code Online (Sandbox Code Playgroud)

选择器匹配哪些元素?

  1. 匹配的div:matches(.foo, .bar)
    第一个div元素具有"foo"类,第二个div元素具有"bar"类,因此每个元素在:matches()伪类中满足其各自的选择器参数.

  2. 匹配div:matches(.foo, .bar)
    的第三个div元素有两个类,因此它匹配两个选择器参数.

    关于特异性的说明:这两个参数具有相同的特异性,使得总体特异性(0, 1, 1),但是当一个元素匹配具有不同特异性值的多个选择器参数时,规范说明特异性是匹配的最具体参数的特异性.

  3. div:has(.foo, .bar)
    这些div元素的每一个都匹配一个后代元素(在本例中为a p),其中一个类与:has()伪类中的相应选择器参数相匹配.

  4. Matched bydiv:has(.foo, .bar)
    div元素具有div.foo后代和p.bar后代,因此它满足两个相对选择器参数.

    关于特异性的说明:由于:has()尚未处于快速剖析中,因此暂时从CSS中排除,因此特异性概念根本不适用.有计划在快速配置文件中包含一个限制版本用于CSS,但目前还没有具体的内容.任何新的发展都将在适当的时候增加.

  5. Matched by div:matches(.foo, .bar)div:has(.foo, .bar)
    This div元素匹配两个伪类:

    • .foo(因为它有"foo"类),和
    • 一个"bar"类的后代.

    此元素也将匹配div:matches(.foo, .bar):has(.foo, .bar),这将是有效的4级选择器,因为复合选择器可以具有任何伪类的组合.

:matches()和之间的另一个区别:has():has()接受所谓的相对选择器.相对选择器具有范围 ; 选择器作用域本身就是一个完整的主题,但是为了这个目的:has(),作用域元素始终是将:has()伪类附加到的元素.但是,更重要的是,相对选择器可以具有隐式后代组合子,或者使用组合器明确地开始>,+或者~- 这个组合器将相对选择器的其余部分链接到其作用域元素.

例如,尽管:has()默认为一个祖先子孙关系,则可以通过与开始的相对选择器+,它便成为相邻的同胞关系:ul:has(+ p)任何匹配ul,其直接后跟一个元件p(不一定一个包含一个p后代) .

至于:matches(),虽然概述表说它接受了一个复合选择器列表,但AFAIK尚未确定它是否会采用复合选择器或复杂选择器的列表,以及哪个配置文件(快速或完整).但是复合选择器只是Selectors 3当前称为简单选择器序列的新名称,复杂选择器是整个系列的复合选择器和组合器.在这方面,相对选择器更像是复杂的选择器.有关选择器中使用的各种术语的非详尽列表,请参阅此答案.


1 是的,复数形式的"参数" - 在选择器4中,:not()现在可以接受选择器列表而不是单个简单选择器.这是一个急需的增强功能,但它也是为了使其与其他新的功能伪类保持一致.

  • 请记住,截至2015年,这两个功能都没有已知的实现(在`: - * - any()`之外,不适合生产使用,而jQuery中的非标准`:has()` ).请不要留下评论说你无法让这些选择器工作,也不要试图使示例代码段可以运行.但是如果你找到一个支持这些功能的实现,请*做*告诉 - 我很想知道谁是第一个跳枪的人. (2认同)