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

时间:2011-04-04 23:50:50

标签: css css3 css-selectors

有没有办法选择匹配(或不匹配)任意选择器的每个第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>

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

有人可以解释原因吗?

8 个答案:

答案 0 :(得分:114)

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

:nth-child() pseudo-class计算同一父母下其兄弟姐妹的所有元素。它不仅仅计算与选择器其余部分匹配的兄弟姐妹。类似地,:nth-of-type() pseudo-class计算共享相同元素类型的兄弟姐妹,它指的是HTML中的标记名称,而不是选择器的其余部分。

这也意味着如果同一父元素的所有子元素具有相同的元素类型,例如,对于只有子元素为tr元素的表体或者只有子元素为{的列表元素。 {1}}元素,然后li:nth-child()的行为相同,即对于:nth-of-type()的每个值,an+b:nth-child(an+b)将匹配同一组元件。

实际上,给定复合选择器中的所有简单选择器(包括:nth-of-type(an+b):nth-child()之类的伪类,彼此独立地工作,而不是查看由选择器的其余部分匹配的元素的子集

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

:not()

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

  

选择符合以下所有独立条件的任何table.myClass tr.row:nth-child(odd) table.myClass tr:nth-child(odd).row 元素:

     
      
  • 这是其父母的奇数孩子;
  •   
  • 它有“行”类;和
  •   
  • 它是具有“myClass”类的tr元素的后代。
  •   

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

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

tr

使用相应的CSS:

$('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');
});

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

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

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


对于它的价值,有一个建议an extension to the :nth-child() notation被添加到选择器级别4,用于选择匹配给定选择器的每个第n个子节点。 2

用于过滤匹配的选择器作为//table[contains(concat(' ', @class, ' '), ' myClass ')]//tr[contains(concat(' ', @class, ' '), ' row ')][position() mod 2)=1] 的参数提供,这也是由于选择器如何在序列中彼此独立地操作,如现有选择器语法所指示的那样。所以在你的情况下,它看起来像这样:

:nth-child()

(一位精明的读者会立即注意到这应该是table.myClass tr:nth-child(odd of .row) ,因为简单的选择器:nth-child(odd of tr.row)tr也是彼此独立运作的。接受选择器的函数伪类的问题,我不想在这个答案的中间打开一些蠕虫。相反,我会假设大多数网站不会有除{{{{{{{ 1}}元素作为表体中彼此的兄弟姐妹,这将使任一选项在功能上等效。)

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


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

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

答案 1 :(得分:6)

不是真的..

quote from the docs

  

:nth-child伪类匹配   具有+ b-1 兄弟姐妹的元素   在文档树之前,对于a   n给出正值或零值,   并有一个父元素。

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

答案 2 :(得分:1)

如果所有选择器都具有相同的父类,则使用该类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>

答案 3 :(得分: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 class的元素。

在这种情况下,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,你必须像这样写< / p>

.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时应用了css, <p>的第5个元素。

答案 4 :(得分:0)

您可以使用xpath执行此操作。像//tr[contains(@class, 'row') and position() mod 2 = 0]这样的东西可能有效。还有其他SO问题扩展到如何更准确地匹配类的细节。

答案 5 :(得分: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>

答案 6 :(得分: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;
}

希望能帮助那些遵循“欺骗”线索的人解决“忽略隐藏元素”的问题!

答案 7 :(得分:0)

不是“有人可以解释为什么吗?”的答案因为其他答案已经解释过了。

但作为针对您的情况的一种可能解决方案,您可以为行和单元格使用自定义标签,例如 <tr-row><td-row>,然后 :nth-of-type() 应该可以工作。不要忘记分别设置样式 display: table-row;display: table-cell; 以使它们仍然像表格单元格一样工作。