我可以组合:nth-​​child()或:nth-​​of-type()与任意选择器?

ata*_*mir 103 css css-selectors css3

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

table.myClass tr.row:nth-child(odd) {
  ...
}
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)

:nth-child()似乎只计算所有tr元素,无论它们是否属于"行"类,所以我最终得到一个偶数 "行"元素而不是我正在寻找的两个元素.同样的事情发生在:nth-of-type().

有人可以解释原因吗?

Bol*_*ock 123

这是一个非常普遍的问题,由于对工作方式:nth-child():nth-of-type()工作的误解而产生.不幸的是,目前还没有基于选择器的解决方案,因为选择器没有提供一种方法来匹配基于奇数,偶数或任何an+bwhere a != 1和模式的模式匹配任意选择器的第n个子节点b != 0.这不仅仅是类选择器,属性选择器,否定以及简单选择器的更复杂组合.

: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
Run Code Online (Sandbox Code Playgroud)

翻译成英文,他们都意味着:

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

  • 这是其父母的奇数孩子;
  • 它有"行"类; 和
  • 它是table具有类"myClass" 的元素的后代.

(你会注意到我在这里使用了无序列表,只是为了把这一点推回家)

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

$('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');
});
Run Code Online (Sandbox Code Playgroud)

使用相应的CSS:

table.myClass tr.row.odd {
  ...
}
Run Code Online (Sandbox Code Playgroud)

如果您使用Selenium等自动化测试工具或使用lxml等工具处理HTML,许多工具都允许XPath作为替代方案:

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

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


对于它的价值,有一个建议是:nth-child()符号的扩展添加到选择器级别4,以便选择与给定选择器匹配的每个第n个子级.2

过滤器匹配的选择器作为参数提供:nth-child(),同样由于选择器如何按照现有选择器语法指示的顺序彼此独立地操作.所以在你的情况下,它看起来像这样:

table.myClass tr:nth-child(odd of .row)
Run Code Online (Sandbox Code Playgroud)

(精明的读者会立即注意到,这应该是:nth-child(odd of tr.row)相反的,因为简单的选择器tr:nth-child()可以彼此独立地运行.这是接受选择器的功能伪类的问题之一,我可以使用蠕虫.而不是在这个答案的中间打开.相反,我将假设大多数网站tr在表体中没有任何其他元素而不是元素作为彼此的兄弟姐妹,这将使任一选项在功能上等效.)

当然,作为全新规范中的全新提案,这可能直到未来几年才会实现.与此同时,你必须坚持使用脚本,如上所述.


1 如果指定了类型或通用选择器,则必须先使用它.然而,这并没有改变选择者从根本上如何运作; 它只不过是一种语法怪癖.

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

  • "(你会注意到我在这里使用无序列表,只是为了把重点放在家里)"我希望更多的人有意识地使用有序与无序子弹.谢谢您的回答. (3认同)
  • @The Red Pea:我最讨厌的 HTML 之一:“按从最高/最低到最低/最高的顺序:”后面跟着一个无序列表。我的意思是来吧,认真的吗? (3认同)

Gab*_*oli 6

并不是的..

引用文档

:nth-child伪类相匹配,其具有+ B-1的元素的兄弟姐妹之前它在文档树,对于一个给定的正或零值对于n,并且具有父元素.

它是一个自己的选择器,不与类结合.在你的规则中,它必须同时满足两个选择器,因此:nth-child(even)如果它们碰巧有.row类,它将显示表行.