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

Есть ли способ выбрать каждый 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().

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

Ответы [ 5 ]

119 голосов
/ 05 апреля 2011

Это очень распространенная проблема, которая возникает из-за неправильного понимания того, как :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().

6 голосов
/ 05 апреля 2011

Не совсем ..

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

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

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

0 голосов
/ 24 апреля 2019

Вот ваш ответ

<!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 голосов
/ 05 ноября 2016

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

0 голосов
/ 04 августа 2016

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 и thru Он применил CSS к 1, 2, 3, 4, 5 элементу <p>.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...