#javascript #jquery #css
Вопрос:
Есть ли способ выбрать каждого 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()
.
Может кто-нибудь объяснить, почему?
Комментарии:
1. По состоянию на октябрь 2021 года указан n-й ребенок(n из S) (где S-селектор), но, насколько я могу судить, в настоящее время реализован только в Safari, см., например developer.mozilla.org/en-US/docs/Web/CSS/:nth-child
Ответ №1:
Это очень распространенная проблема, которая возникает из-за непонимания того, как :nth-child(An B)
и :nth-of-type()
как работать.
В селекторах уровня 3 :nth-child()
псевдокласс подсчитывает элементы среди всех своих братьев и сестер, находящихся под одним родителем. Он не учитывает только братьев и сестер, которые соответствуют остальной части селектора. Аналогично, :nth-of-type()
псевдокласс подсчитывает братьев и сестер, имеющих один и тот же тип элемента, который ссылается на имя тега в HTML, а не на остальную часть селектора.
Это также означает, что если все дети одного родителя имеют тот же тип элемента, например, в случае таблицы, тело которого только дети tr
стихии или элемента списка, чьи дети только несколько li
элементов, а затем :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
элемент, соответствующий всем следующим независимым условиям:
- он является нечетным дочерним элементом своего родителя;
- он имеет класс «строка»; и
- он является потомком
table
элемента, имеющего класс «MyClass».
(вы заметите, что я использую здесь неупорядоченный список, просто чтобы подчеркнуть суть)
Селекторы уровня 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, или очищаете HTML с помощью таких инструментов, как BeautifulSoup, многие из этих инструментов позволяют использовать XPath в качестве альтернативы:
//table[contains(concat(' ', @class, ' '), ' myClass ')]//tr[contains(concat(' ', @class, ' '), ' row ')][position() mod 2)=1]
Другие решения, использующие различные технологии, оставлены читателю в качестве упражнения; это всего лишь краткий, надуманный пример для иллюстрации.
1 Если вы указываете тип или универсальный селектор, он должен быть первым. Однако это не меняет фундаментальной работы селекторов; это не более чем синтаксическая причуда.
2 Первоначально это было предложено как :nth-match()
, однако, поскольку он по-прежнему учитывает элемент только по отношению к его братьям и сестрам, а не ко всем другим элементам, соответствующим данному селектору, с 2014 года он был перепрофилирован как расширение существующего :nth-child()
вместо этого.
Комментарии:
1. «(вы заметите, что я использую здесь неупорядоченный список, просто чтобы подчеркнуть суть)» Я хотел бы, чтобы как можно больше людей были настолько сознательны в использовании упорядоченных и неупорядоченных пуль. Спасибо вам за ваш ответ.
2. @Красная горошина: Одна из моих самых больших домашних обид HTML: «В порядке от самого высокого/самого низкого до самого низкого/самого высокого:», за которой следует неупорядоченный список. Я имею в виду, да ладно, серьезно?
Ответ №2:
Не совсем..
:nth-child
Псевдокласс соответствует элементу, у которого перед ним в дереве документов есть братья и сестры b-1, для заданного положительного или нулевого значения для n и имеет родительский элемент.
Это собственный селектор, который не сочетается с классами. В вашем правиле он просто должен удовлетворять обоим селекторам одновременно, поэтому он покажет строки :nth-child(even)
таблицы, если у них также есть .row
класс.
Ответ №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.
В этом случае 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 n-го типа, это может быть
.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>
.
Комментарии:
1. Насколько это полезно для
<tr>
тегов?
Ответ №4:
Возможно, вы сможете сделать это с помощью xpath. что-то вроде //tr[contains(@class, 'row') and position() mod 2 = 0]
этого может сработать. Есть и другие вопросы SO, расширяющие детали того, как более точно сопоставлять классы.
Ответ №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>
Ответ №6:
Все вопросы, связанные с использованием n-го ребенка и пропуском скрытых тегов, похоже, перенаправляются как дураки этого, поэтому я оставлю это здесь. Я наткнулся на этот блог 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;
}
Надеюсь, это поможет кому-то, кто идет по следу обмана, чтобы игнорировать вопросы о скрытых элементах!
Комментарии:
1. Я бы хотел поддержать это, но для этого нужна рабочая демонстрация.
2. Насколько я помню, на самом деле это было не так надежно, как казалось изначально, — теперь я бы пошел с комментарием с самым высоким голосованием, это невозможно.
Ответ №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>
Ответ №8:
Не ответ на вопрос «Может ли кто-нибудь объяснить, почему?», поскольку другие ответы объяснили.
Но в качестве одного из возможных решений вашей ситуации вы можете использовать пользовательские теги для строк и ячеек, скажем <tr-row>
<td-row>
, тогда :nth-of-type()
это должно сработать. Не забудьте задать стиль display: table-row;
и display: table-cell;
, соответственно, заставить их работать как ячейки таблицы.