Могу ли я объединить: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;
соответственно, чтобы они по-прежнему работали как ячейки таблицы.