Могу ли я объединить:nth-child() или:nth-of-type() с произвольным селектором?

Есть ли способ выбрать каждый 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 элементы, независимо от того, принадлежат ли они к классу "row", поэтому я получаю один четный элемент "row" вместо двух, которые я ищу. То же самое происходит с :nth-of-type(),

Может кто-нибудь объяснить почему?

9 ответов

Решение

Это очень распространенная проблема, которая возникает из-за неправильного понимания того, как :nth-child() а также :nth-of-type() Работа. К сожалению, в настоящее время пока нет решения на основе селектора, поскольку селекторы не обеспечивают способ сопоставления n-го дочернего элемента, который соответствует произвольному селектору, на основе шаблона, такого как нечетный, четный или любой другой an+b где a != 1 а также 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

В переводе на английский они оба означают:

Выберите любой 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, или обрабатываете HTML с помощью таких инструментов, как lxml, многие из этих инструментов позволяют использовать 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() вместо.

На самом деле, нет..

цитата из документов

:nth-child Псевдокласс соответствует элементу, у которого в дереве документа содержится +b-1 одноуровневых элементов перед заданным положительным или нулевым значением для n, и имеет родительский элемент.

Это собственный селектор, который не сочетается с классами. В вашем правиле он должен удовлетворять оба селектора одновременно, поэтому он покажет :nth-child(even) строки таблицы, если они также имеют .row учебный класс.

2023 ответ: Теперь можно!

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

Обобщенная версия (спецификация ):

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

...в котором<nth>является2,3n + 1,-n + 3,oddили другие допустимые значения и<selector>представляет собой список селекторов, который может быть сложным.

На момент написания эта функция поддерживается только в Chrome 111+ (2023/03/07, также для Android), Firefox 113+ (2023/05/09, также для Android), Edge 111+ (2023/03/ 13) и Safari 9+ (01.10.2015, также для iOS), согласно caniuse.com.

Попробуй это:

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-child а также nth-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-child а также nth-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;
}

но если вы используете 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 а затем он применил CSS на 1, 2, 3, 4, 5 элемент <p>,

Вот твой ответ

<!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>

Все вопросы, связанные с использованием nth-child и пропуском скрытых тегов, похоже, перенаправляются как дубликаты этого, поэтому я оставлю это здесь. Я наткнулся на этот блог https://blog.blackbam.at/2015/04/09/css-nth-child-selector-ignore-hidden-element/, который использует умный подход css, чтобы nth-child игнорировал скрытые элементы, следующее:

Следующий 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;
}

Надеюсь, что это поможет кому-то, кто идет по обманчивой тропе в вопросах игнорирования скрытых элементов!

Вы можете сделать это с помощью xpath. что-то вроде //tr[contains(@class, 'row') and position() mod 2 = 0] может работать. Существуют и другие вопросы SO, в которых подробно описывается, как более точно сопоставлять классы.

ЕСЛИ у вас есть один и тот же родительский класс для всех селекторов, тогда вы используете этот класс 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>

Не ответ на вопрос "Кто-нибудь может объяснить, почему?" поскольку другие ответы объяснили.

Но в качестве одного из возможных решений вашей ситуации вы можете использовать настраиваемые теги для строк и ячеек, например <tr-row>, <td-row>, тогда :nth-of-type()должно сработать. Не забудьте установить стиль display: table-row; а также display: table-cell; соответственно, чтобы они по-прежнему работали как ячейки таблицы.

Другие вопросы по тегам