我可以将 :nth-child() 或 :nth-of-type() 与任意选择器结合使用吗? [英] Can I combine :nth-child() or :nth-of-type() with an arbitrary selector?

查看:29
本文介绍了我可以将 :nth-child() 或 :nth-of-type() 与任意选择器结合使用吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有没有办法选择每一个匹配(或不匹配)任意选择器的孩子?例如,我想选择每个奇数表行,但在行的子集中:

table.myClass tr.row:nth-child(odd) {...}

<tr><td>行<tr class="row"><!-- 我想要这个--><td>行<tr class="row"><td>行<tr class="row"><!-- 还有这个--><td>行

但是 :nth-child() 似乎只是计算所有 tr 元素,无论它们是否属于row"类,所以我结束用一个 even row" 元素代替我正在寻找的两个.:nth-of-type() 也会发生同样的事情.

有人能解释一下原因吗?

解决方案

这是一个很常见的问题,由于对:nth-child(An+B)>:nth-of-type() 工作.

在选择器级别 3 中,:nth-child() 伪类 计算同一父项下所有 兄弟姐妹中的元素.它不只计算与选择器其余部分匹配的兄弟姐妹.同样,:nth-of-type() 伪类 计算共享相同元素类型的兄弟姐妹,它指的是 HTML 中的标签名称,而不是选择器的其余部分.

这也意味着,如果同一个父元素的所有子元素都属于相同的元素类型,例如在表体的唯一子元素是 tr 元素或列表元素的情况下子元素是 li 元素,然后 :nth-child():nth-of-type() 将表现相同,即对于每个值对于 An+B,:nth-child(An+B):nth-of-type(An+B) 将匹配相同的元素集.>

实际上,给定复合选择器中的所有简单选择器,包括:nth-child():not() 等伪类,都可以相互独立,而不是查看与选择器其余部分匹配的元素的子集.

这也意味着在每个单独的复合选择器中的简单选择器之间没有顺序的概念1,这意味着例如以下两个选择器是等价的:>

table.myClass tr.row:nth-child(odd)table.myClass tr:nth-child(odd).row

翻译成英文,它们的意思都是:

<块引用>

选择与以下所有独立条件匹配的任何 tr 元素:

  • 它是其父节点的奇数子节点;
  • 它有row"类;和
  • 它是具有myClass"类的 table 元素的后代.

(你会注意到我在这里使用了一个无序列表,只是为了说明问题)

选择器级别 4 试图通过允许 :nth-child(An+B of S)2 接受任意选择器参数 S,同样是由于选择器如何在复合选择器中彼此独立运行按照现有选择器语法的规定.所以在你的情况下,它看起来像这样:

table.myClass tr:nth-child(.row 的奇数)

当然,作为全新规范中的全新提案,在 几年后.

与此同时,您必须使用脚本来过滤元素并相应地应用样式或额外的类名.例如,以下是使用 jQuery 的常见解决方法(假设表中只有一个行组填充了 tr 元素):

$('table.myClass').each(function() {//请注意,令人困惑的是,jQuery 的过滤器伪代码是 0 索引的//而 CSS :nth-child() 是 1-indexed$('tr.row:even').addClass('odd');});

使用相应的CSS:

table.myClass tr.row.odd {...}

如果您使用 Selenium 等自动化测试工具或使用 BeautifulSoup 等工具抓取 HTML,其中许多工具都允许使用 XPath 作为替代:

//table[contains(concat(' ', @class, ' '), ' myClass ')]//tr[contains(concat(' ',@class, ' '), ' row ')][position() mod 2)=1]

使用不同技术的其他解决方案留给读者作为练习;这只是一个简短的、人为的示例,用于说明.


1 如果你指定一个类型或通用选择器,它必须放在第一位.然而,这并没有改变选择器的基本工作方式;这只不过是句法上的怪癖.

2 这最初被提议为 :nth-match(),但是因为它仍然只计算一个元素相对于它的兄弟元素,而不是每个元素与给定选择器匹配的其他元素,自 2014 年起,它已被重新用作现有 :nth-child() 的扩展.

Is there a way to select every nth child that matches (or does not match) an arbitrary selector? For example, I want to select every odd table row, but within a subset of the rows:

table.myClass tr.row:nth-child(odd) {
  ...
}

<table class="myClass">
  <tr>
    <td>Row
  <tr class="row"> <!-- I want this -->
    <td>Row
  <tr class="row">
    <td>Row
  <tr class="row"> <!-- And this -->
    <td>Row
</table>

But :nth-child() just seems to count all the tr elements regardless of whether or not they're of the "row" class, so I end up with the one even "row" element instead of the two I'm looking for. The same thing happens with :nth-of-type().

Can someone explain why?

解决方案

This is a very common problem that arises due to a misunderstanding of how :nth-child(An+B) and :nth-of-type() work.

In Selectors level 3, the :nth-child() pseudo-class counts elements among all of their siblings under the same parent. It does not count only the siblings that match the rest of the selector. Similarly, the :nth-of-type() pseudo-class counts siblings sharing the same element type, which refers to the tag name in HTML, and not the rest of the selector.

This also means that if all the children of the same parent are of the same element type, for example in the case of a table body whose only children are tr elements or a list element whose only children are li elements, then :nth-child() and :nth-of-type() will behave identically, i.e. for every value of An+B, :nth-child(An+B) and :nth-of-type(An+B) will match the same set of elements.

In fact, all simple selectors in a given compound selector, including pseudo-classes such as :nth-child() and :not(), work independently of one another, rather than looking at the subset of elements that are matched by the rest of the selector.

This also implies that there is no notion of order among simple selectors within each individual compound selector1, which means for example the following two selectors are equivalent:

table.myClass tr.row:nth-child(odd)
table.myClass tr:nth-child(odd).row

Translated to English, they both mean:

Select any tr element that matches all of the following independent conditions:

  • it is an odd-numbered child of its parent;
  • it has the class "row"; and
  • it is a descendant of a table element that has the class "myClass".

(you'll notice my use of an unordered list here, just to drive the point home)

Selectors level 4 seeks to rectify this limitation by allowing :nth-child(An+B of S)2 to accept an arbitrary selector argument S, again due to how selectors operate independently of one another in a compound selector as dictated by the existing selector syntax. So in your case, it would look like this:

table.myClass tr:nth-child(odd of .row)

Of course, being a brand new proposal in a brand new specification, this probably won't see implementation until a few years down the road.

In the meantime, you'll have to use a script to filter elements and apply styles or extra class names accordingly. For example, the following is a common workaround using jQuery (assuming there is only one row group populated with tr elements within the table):

$('table.myClass').each(function() {
  // Note that, confusingly, jQuery's filter pseudos are 0-indexed
  // while CSS :nth-child() is 1-indexed
  $('tr.row:even').addClass('odd');
});

With the corresponding CSS:

table.myClass tr.row.odd {
  ...
}

If you're using automated testing tools such as Selenium or scraping HTML with tools like BeautifulSoup, many of these tools allow XPath as an alternative:

//table[contains(concat(' ', @class, ' '), ' myClass ')]//tr[contains(concat(' ', @class, ' '), ' row ')][position() mod 2)=1]

Other solutions using different technologies are left as an exercise to the reader; this is just a brief, contrived example for illustration.


1 If you specify a type or universal selector, it must come first. This does not change how selectors fundamentally work, however; it's nothing more than a syntactic quirk.

2 This was originally proposed as :nth-match(), however because it still counts an element relative only to its siblings, and not to every other element that matches the given selector, it has since as of 2014 been repurposed as an extension to the existing :nth-child() instead.

这篇关于我可以将 :nth-child() 或 :nth-of-type() 与任意选择器结合使用吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆