Чи можу я поєднати: nth-child () або: nth-of-type () з довільним селектором?


116

Чи є спосіб вибрати кожну п'яту дитину, яка відповідає (або не відповідає) довільному селектору ? Наприклад, я хочу вибрати кожен непарний ряд таблиці, але в підмножині рядків:

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().

Може хтось пояснить, чому?

Відповіді:


144

Це дуже поширена проблема, яка виникає через нерозуміння того, як :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 рівня для конкретної мети вибору кожної п’ятої дитини, що відповідає заданому селектору. 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().


3
"(ви помітите моє використання не упорядкованого списку тут, просто для того, щоб загнати точку додому)" Я хотів би, щоб більше людей надумали про їх використання впорядкованих проти не упорядкованих куль. Спасибі за вашу відповідь.
Червоний горох

1
@The Red Pea: Один з моїх найбільших HTML вихованців HTML: "Для того, щоб від найвищого / нижчого до найнижчого / найвищого:" слідував не упорядкований список. Я маю на увазі давай, серйозно?
BoltClock

6

Не зовсім..

цитата з док

:nth-childПсевдо-клас відповідає елементу , який має + B-1 брат і сестра перед цим в дереві документа , для заданого позитивного або нульового значення для п, і має батьківський елемент.

Це власний вибір і не поєднується з класами. У вашому правилі він просто повинен задовольняти обидва селектора одночасно, тому він покаже :nth-child(even)рядки таблиці, якщо вони також мають .rowклас.


0

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 ми хочемо приховати всі елементи класу відпочинку.

В цьому випадку 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- абзаци, а інші є діловими, тому в цьому випадку, якщо ви використовуєте, 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>.


Наскільки це корисно для <tr>тегів?
Алексіс Вілке

0

Ви можете зробити це за допомогою xpath. щось подібне //tr[contains(@class, 'row') and position() mod 2 = 0]може спрацювати. Існують і інші питання щодо розгортання інформації щодо того, як точніше відповідати класам.


0

Ось ваша відповідь

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

Усі запитання щодо використання 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;
}

Сподіваємось, що допоможе тому, хто слідкує за дурним слідом для ігнорування прихованих елементів!


1
Я хотів би підтримати це, але для цього потрібна робоча демонстрація.
Moob

Нагадую, що це насправді не було настільки надійним, як здавалося спочатку - я б зараз пішов із коментарем, який проголосував вгорі, це неможливо.
IrishDubGuy

0

Якщо у вас однаковий батьківський клас для всіх селекторів, тоді ви використовуєте цей клас, 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>
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.