Могу ли я объединить: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().

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

4 74

4 ответа:

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

The :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(), работает самостоятельно одного другом, а не смотреть на!--37-->подмножество элементов, которым соответствует остальная часть селектора.

это также означает, что нет понятия порядка среди простых селекторов внутри каждого отдельного составного селектора1, что означает, например, что следующие два селектора эквивалентны:

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

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

выберите tr элемент, который соответствует всем следующим независимым условиям:

  • это нечетный ребенок своего родителя;
  • он имеет класс "row"; и
  • является потомком элемента 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() вместо.

не совсем так..

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

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

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

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

но если вы используете 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й элемент <p>.

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