我可以将:nth-​​child()或:nth-​​of-type()与任意选择器结合使用吗?


116

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

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>

但是,无论它们是否属于“ row”类,:nth-child()似乎似乎都在计算所有tr元素,因此我最终得到了一个偶数 “ row”元素,而不是我要寻找的两个元素。发生同样的事情:nth-of-type()

有人可以解释为什么吗?

Answers:


144

由于对工作方式:nth-child():nth-of-type()工作的误解,这是一个非常普遍的问题。不幸的是,目前还没有基于选择的解决方案至今,因为选择器不提供一种方法来匹配基础上的模式,如奇数,偶数或任意选择相匹配的第n个孩子an+b,其中a != 1b != 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

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

选择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');
});

使用相应的CSS:

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

如果您使用诸如Selenium之类的自动化测试工具,或者使用诸如lxml之类的工具来处理HTML,则其中许多工具都可以将XPath用作替代方法:

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

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


对于它的价值,有人提议:nth-child()表示法的扩展名添加到选择器级别4,以达到选择与给定选择器匹配的第n个子代的特定目的。2

:nth-child()再次由于选择器如何按照现有选择器语法规定的顺序彼此独立地操作,因此将作为选择项的筛选器提供给。因此,在您的情况下,它看起来像这样:

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

(精明的读者会立即注意到,应该这样做:nth-child(odd of tr.row),因为简单的选择器tr:nth-child()彼此独立运行。这是接受选择器的功能性伪类的问题之一,我会选择一堆蠕虫相反,我将假设大多数站点tr在表主体中除了元素作为彼此的同级元素外,将不具有其他任何元素,这将使两个选项在功能上等效。)

当然,作为全新规范中的全新提案,可能要等到几年后才能实现。同时,您必须坚持使用脚本,如上所述。


1 如果指定类型或通用选择器,则必须排在最前面。但是,这不会改变选择器的基本工作方式。只是语法上的怪异而已。

2 最初被提议为:nth-match(),但是因为它仍然仅相对于其同级而不是与给定选择器匹配的所有其他元素都相对于一个元素进行计数,自2014年起,该元素已被重新用作现有元素的扩展:nth-child()


3
“((您会注意到我在这里使用的是无序列表,只是为了说明问题)”)我希望更多的人对使用有序和无序子弹有一定的刻意。谢谢您的回答。
红豌豆

1
@The Red Pea:我最大的HTML宠物怒吼之一:“按从最高/最低到最低/最高的顺序:”后跟无序列表。我的意思是说,认真吗?
BoltClock

6

并不是的..

引用文档

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

它是自己的选择器,并且不与类组合。在您的规则中,它只需要同时满足两个选择器,因此:nth-child(even)如果它们恰好都具有.row该类,它将显示表行。


0

nth-of-type根据元素的相同类型的索引工作,但nth-child无论同级元素是什么类型,都仅根据索引工作。

例如

<div class="one">...</div>
<div class="two">...</div>
<div class="three">...</div>
<div class="four">...</div>
<div class="five">...</div>
<div class="rest">...</div>
<div class="rest">...</div>
<div class="rest">...</div>
<div class="rest">...</div>
<div class="rest">...</div>

假设在html上方,我们想隐藏所有具有rest类的元素。

在这种情况下nth-childnth-of-type它将工作完全相同,因为所有元素都是同一类型,<div>因此css应该是

.rest:nth-child(6), .rest:nth-child(7), .rest:nth-child(8), .rest:nth-child(9), .rest:nth-child(10){
    display:none;
}

要么

.rest:nth-of-type(6), .rest:nth-of-type(7), .rest:nth-of-type(8), .rest:nth-of-type(9), .rest:nth-of-type(10){
    display:none;
}

现在您一定想知道两者之间有什么区别nth-childnth-of-type所以这就是区别

假设html是

<div class="one">...</div>
<div class="two">...</div>
<div class="three">...</div>
<div class="four">...</div>
<div class="five">...</div>
<p class="rest">...</p>
<p class="rest">...</p>
<p class="rest">...</p>
<p class="rest">...</p>
<p class="rest">...</p>

在上面的html中,.rest元素的类型不同于其他元素,是.rest段落,其他元素是div,因此在这种情况下,如果使用nth-child,则必须这样编写

.rest:nth-child(6), .rest:nth-child(7), .rest:nth-child(8), .rest:nth-child(9), .rest:nth-child(10){
    display:none;
}

但是如果您使用nth-of-type css可以这样

.rest:nth-of-type(1), .rest:nth-of-type(2), .rest:nth-of-type(3), .rest:nth-of-type(4), .rest:nth-of-type(5){
    display:none;
}

由于.rest元素的类型<p>如此,因此在这里nth-of-type检测的类型,.rest然后他在的第1、2、3、4、5个元素上应用了CSS <p>


这对于<tr>标签有多大用处?
Alexis Wilke

0

您也许可以使用xpath做到这一点。类似的东西//tr[contains(@class, 'row') and position() mod 2 = 0]可能会起作用。还有其他SO问题扩展了如何更精确地匹配类的细节。


0

这是你的答案

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>TEST</title>

  <style>

    .block {
      background: #fc0;
      margin-bottom: 10px;
      padding: 10px;
    }
    /* .large > .large-item:nth-of-type(n+5) {
      background: #f00;
    } */

    .large-item ~ .large-item ~ .large-item ~ .large-item ~ .large-item {
      background: #f00;
    }

  </style>
</head>
<body>

<h1>Should be the 6th Hello Block that start red</h1>
<div class="small large">
  <div class="block small-item">Hello block 1</div>
  <div class="block small-item large-item">Hello block 2</div>
  <div class="block small-item large-item">Hello block 3</div>
  <div class="block small-item large-item">Hello block 4</div>
  <div class="block small-item large-item">Hello block 5</div>
  <div class="block small-item large-item">Hello block 6</div>
  <div class="block small-item large-item">Hello block 7</div>
  <div class="block small-item large-item">Hello block 8</div>
</div>

</body>
</html>

0

关于使用nth-child和跳过隐藏标签的所有问题似乎都被重定向为对此的重复,因此我将其留在此处。我遇到了这个博客https://blog.blackbam.at/2015/04/09/css-nth-child-selector-ignore-hidden-element/,该博客使用聪明的CSS方法使nth-child忽略隐藏的元素,如下:

无论哪个元素具有cpw类,以下CSS都会向每个第二个可见元素添加边距权限。

.cpw {
    display:none;
}

.video_prewrap {
    margin-right:20px;
}

.video_prewrap:nth-child(2n) {
    margin-right:0;
}

.cpw ~ .video_prewrap:nth-child(2n) {
    margin-right:20px;
}

.cpw ~ .video_prewrap:nth-child(2n-1) {
    margin-right:0;
}

希望这对跟随重复路径的人提供帮助,以解决忽略隐藏元素的问题!


1
我想对此表示赞同,但需要一个有效的演示。
Moob

我的回忆是,这实际上并不像最初看起来那样健壮-我现在要接受最高票数的评论,这是不可能的。
IrishDubGuy

0

如果所有选择器都具有相同的父类,则使用该类,document.querySelector("main .box-value:nth-child(3) select.priorityOption"); 因为在这种情况下document.querySelector("main .box-value select.priorityOption:nth-child(3)");不起作用。谢谢

<div class="card table">
    <div class="box">
        <div class="box-value">
            <select class="priorityOption">
                <option value="">--</option>
                <option value="">LOREM</option>
                <option value="">LOREM</option>
            </select>
        </div>

        <div class="box-value">
            <select class="priorityOption">
                <option value="">--</option>
                <option value="">LOREM</option>
                <option value="">LOREM</option>
            </select>
        </div>

        <div class="box-value">
            <select class="priorityOption">
                <option value="">--</option>
                <option value="">LOREM</option>
                <option value="">LOREM</option>
            </select>
        </div>
    </div>
</div>
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.