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

Can I combine :nth-child() or :nth-of-type() with an arbitrary selector?

提问人:atanamir 提问时间:4/5/2011 最后编辑:BoltClockatanamir 更新时间:9/20/2023 访问量:46271

问:

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

有人可以解释为什么吗?

css css-selectors

评论

3赞 A Haworth 10/29/2021
截至 2021 年 10 月,指定了第 n-child(n of S)(其中 S 是选择器),但据我所知,目前仅在 Safari 中实现,参见例如 developer.mozilla.org/en-US/docs/Web/CSS/:nth-child
0赞 mfluehr 7/27/2022
ChromiumFirefox都有未解决的问题需要实现。:nth-child(An+B of S)

答:

8赞 Gabriele Petrioli 4/5/2011 #1

没有。。

引用文档

伪类匹配 具有 AN+B-1 同级的元素 在文档树中,对于 给定 n 的正值或零值, 并具有父元素。:nth-child

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

173赞 BoltClock 4/5/2011 #2

现在对新语法的支持非常好,因此您可以使用:

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

这是一个非常常见的问题,由于对工作方式和工作的误解而出现。:nth-child(An+B):nth-of-type()

在选择器级别 3 中,:nth-child() 伪类对同一父级下所有同级的元素进行计数。它不仅计算与选择器其余部分匹配的同级。

类似地,:nth-of-type() 伪类对共享相同元素类型的同级元素进行计数,该元素类型指的是 HTML 中的标记名称,而不是选择器的其余部分。

这也意味着,如果同一父项的所有子项都属于相同的元素类型,例如,表体中唯一的子项是元素,或者列表元素的唯一子项是元素,则 和 将具有相同的行为,即对于 An+B 的每个值,并且将匹配同一组元素。trli:nth-child():nth-of-type():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(odd of .row)

您还可以使用脚本来筛选元素并相应地应用样式或额外的类名。例如,以下是使用 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 等自动化测试工具,或者使用 BeautifulSoup 等工具抓取 HTML,其中许多工具都允许使用 XPath 作为替代方案:

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

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


1 如果指定类型或通用选择器,则必须将其放在首位。然而,这并没有从根本上改变选择器的工作方式;这只不过是一种句法上的怪癖。

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

评论

5赞 Nate Anderson 8/28/2016
“(你会注意到我在这里使用了无序列表,只是为了把重点带回家)”我希望更多的人对他们使用有序和无序子弹进行深思熟虑。谢谢你的回答。
3赞 BoltClock 8/28/2016
@The Red Pea:我最讨厌的 HTML 之一:“按从最高/最低到最低/最高顺序排列:”,后面跟着一个无序列表。我的意思是来吧,认真的?
0赞 Ingo Steinke 2/23/2023
这不是误解,而是 CSS 功能请求,请参阅 bram.us/2020/03/16/css-nth-of-class-selector
0赞 BoltClock 3/26/2023
@Ingo Steinke:这个问题没有被表述为功能请求。它是基于对 :nth-child() 工作原理的误解。
2赞 Gaurav Aggarwal 8/4/2016 #3

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 类的元素。

在这种情况下,并且将完全相同,因为所有元素都属于相同的类型,因此 css 应该是nth-childnth-of-type<div>

.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;
}

现在你一定想知道第 n 个子类型和第 n 个类型有什么区别,所以这就是区别

假设 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中,元素的类型与其他元素不同,是段落,其他元素是div,所以在这种情况下,如果你使用,你必须这样写.rest.restnth-child

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

但是,如果您使用第n种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;
}

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

评论

0赞 Alexis Wilke 10/13/2016
这对标签有多大用处?<tr>
1赞 the8472 11/5/2016 #4

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

1赞 Pocketninja 4/24/2019 #5

这是你的答案

<!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>
1赞 IrishDubGuy 9/11/2019 #6

所有关于使用 nth-child 和跳过隐藏标签的问题似乎都被重定向为这个标签的骗子,所以我会把它留在这里。我遇到了这个博客 https://blog.blackbam.at/2015/04/09/css-nth-child-selector-ignore-hidden-element/ 它使用一种巧妙的 css 方法来使第 n 个孩子忽略隐藏的元素,如下所示:

以下 CSS 为每秒可见元素添加一个边距右,无论哪个元素具有 cpw 类。

.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;
}

希望这对那些正在追随忽略隐藏元素问题的人有所帮助!

评论

3赞 Moob 1/15/2020
我想对此投赞成票,但它需要一个工作演示。
1赞 IrishDubGuy 1/17/2020
我的回忆是,这实际上并不像最初看起来那么强大——我现在会选择得票最高的评论,这是不可能的。
1赞 Jatin Aggarwal 5/4/2020 #7

如果所有选择器都有相同的父类,那么你就使用该类,因为在这种情况下不起作用。谢谢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>
-1赞 Yidi Tool 7/21/2021 #8

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

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

1赞 InSync 3/24/2023 #9

2023 年答案:现在你可以了!

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

通用版本(规格):

:nth-child(<nth> [of <selector>]?) {}

...其中是 、 、 或其他有效值,并且是选择器列表,这可能很复杂。<nth>23n + 1-n + 3odd<selector>

caniuse.com 在撰写本文时,此功能仅在 Chrome 111+(2023/03/07,也适用于 Android)、Firefox 113+(2023/05/09,也适用于 Android)、Edge 111+(2023/03/13)和 Safari 9+(2015/10/01,也适用于 iOS)中受支持。

尝试一下:

/*** First example ***/

/* All odds (2n + 1) */
#example-1 > :nth-child(odd of .foo) {
  background: red;
}

/* Odd evens (4n + 2) */
/* Note how .foo:not(...) is evaluated first */
#example-1 > :nth-child(odd of .foo:not(:nth-child(odd of .foo))) {
  background: yellow;
}

/*** Second example ***/

/* This works */
#example-2 > :nth-of-type(3) {
  background: red;
}

/* This too */
#example-2 > :nth-child(4 of div) {
  background: yellow;
}

/* And so will this */
#example-2 > :nth-last-child(11 of div) {
  background: green;
}

/* Use :nth-last-child() to select from last */
/* First 2 of last 3 of <div>s */
#example-2 > :nth-child(-n + 2 of :nth-last-child(-n + 3 of div)) {
  background: cyan;
}

/* 1st, 4th, 7th... from last */
#example-2 > :nth-last-child(3n + 1 of div) {
  text-decoration: underline;
}

/* ...of which odd elements will be selected */
#example-2 > :nth-last-child(odd of :nth-last-child(3n + 1)) {
  outline: 3px solid black;
}

/*** Other styles ***/

.flex {
  display: flex;
  flex-flow: row wrap;
}

.grid {
  display: grid;
  grid-template: repeat(5, 1fr) / repeat(5, 1fr);
}

.flex > div,
.grid > div {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 100px;
  width: 100px;
  text-align: center;
}

/* 2nd, 3rd, 4th... of both .flex and .grid */
body > :nth-child(n + 2 of .flex, .grid) {
  gap: 10px;
}

/* First 1 of [2nd, 3rd, 4th...] <div>s */
body > :nth-child(-n + 1 of :nth-child(n + 2 of div)) > div {
  background: #ddd;
}

/* 2nd of last 2 of [1st, 2nd, 3rd...] non-<script> from last */
/* ...which means 1st from last */
:nth-child(odd of :nth-last-child(-n + 3 of body > :not(script))) > .foo {
  border-radius: 50%;
}
:nth-child(odd of :nth-last-child(-n + 3 of body > :not(script))) > .foo::after {
  content: '.foo';
  display: block;
}
<div class="flex" id="example-1">
  <div>odd</div>
  <div>even</div>
  <div class="foo">1st odd</div>
  <div class="foo">1st even</div>
  <div class="foo">2nd odd</div>
  <div class="foo">2nd even</div>
  <div class="foo">3rd odd</div>
  <div class="foo">3rd even</div>
</div>

<hr>

<div class="flex" id="example-2">
  <div>1 (15)</div>
  <div class="foo">2 (14)</div>
  <div>3 (13)</div>
  <div class="foo">4 (12)</div>
  <div>5 (11)</div>
  <div>6 (10)</div>
  <div class="foo">7 (9)</div>
  <div>8 (8)</div>
  <div>9 (7)</div>
  <div class="foo">10 (6)</div>
  <div class="foo">11 (5)</div>
  <div>12 (4)</div>
  <div class="foo">13 (3)</div>
  <div>14 (2)</div>
  <div>15 (1)</div>
</div>