Kann ich: nth-child () oder: nth-of-type () mit einem beliebigen Selektor kombinieren?

116

Gibt es eine Möglichkeit, jedes n-te Kind auszuwählen , das mit einem beliebigen Selektor übereinstimmt (oder nicht übereinstimmt) ? Zum Beispiel möchte ich jede ungerade Tabellenzeile auswählen, aber innerhalb einer Teilmenge der Zeilen:

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>

Aber es :nth-child()scheint nur, dass alle trElemente gezählt werden, unabhängig davon, ob sie zur Klasse "row" gehören oder nicht, sodass ich am Ende das eine gerade "row" -Element anstelle der beiden Elemente habe, nach denen ich suche. Das gleiche passiert mit :nth-of-type().

Kann jemand erklären warum?

Atanamir
quelle

Antworten:

144

Dies ist ein sehr häufiges Problem, das aufgrund eines Missverständnisses in Bezug auf Funktionsweise :nth-child()und Funktionsweise :nth-of-type()auftritt. Leider gibt es derzeit noch keine selektorbasierte Lösung, da Selectors keine Möglichkeit bietet, das n-te Kind zu finden, das einem beliebigen Selektor entspricht, basierend auf einem Muster wie ungeradzahlig, geradzahlig oder einem beliebigen an+bWo a != 1und b != 0. Dies geht über reine Klassenselektoren hinaus und umfasst Attributselektoren, Negationen und komplexere Kombinationen einfacher Selektoren.

Die :nth-child()Pseudoklasse zählt Elemente unter allen Geschwistern unter demselben Elternteil. Es werden nicht nur die Geschwister gezählt, die mit dem Rest des Selektors übereinstimmen. In ähnlicher Weise zählt die :nth-of-type()Pseudoklasse Geschwister, die denselben Elementtyp verwenden, der sich auf den Tag-Namen in HTML bezieht, und nicht auf den Rest des Selektors.

Dies bedeutet auch, dass, wenn alle untergeordneten Elemente desselben übergeordneten Elements vom gleichen Elementtyp sind, z. B. im Fall eines Tabellenkörpers, dessen einzige untergeordnete trElemente Elemente sind , oder eines Listenelements, dessen einzige untergeordnete liElemente Elemente sind, sich :nth-child()und :nth-of-type()dasselbe Verhalten verhalten, d. H. für jeden Wert von an+b, :nth-child(an+b)und :nth-of-type(an+b)den gleichen Satz von Elementen entsprechen.

Tatsächlich arbeiten alle einfachen Selektoren in einem bestimmten zusammengesetzten Selektor, einschließlich Pseudoklassen wie :nth-child()und :not(), unabhängig voneinander, anstatt die Teilmenge der Elemente zu betrachten, die mit dem Rest des Selektors übereinstimmen.

Dies impliziert auch, dass es keinen Ordnungsbegriff unter einfachen Selektoren innerhalb jedes einzelnen zusammengesetzten Selektors 1 gibt , was bedeutet, dass beispielsweise die folgenden zwei Selektoren äquivalent sind:

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

Übersetzt ins Englische bedeuten beide:

Wählen Sie ein trElement aus, das allen folgenden unabhängigen Bedingungen entspricht:

  • es ist ein ungeradzahliges Kind seines Elternteils;
  • es hat die Klasse "Zeile"; und
  • Es ist ein Nachkomme eines tableElements mit der Klasse "myClass".

(Sie werden feststellen, dass ich hier eine ungeordnete Liste verwende, nur um den Punkt nach Hause zu bringen.)

Da es derzeit keine reine CSS-Lösung gibt, müssen Sie ein Skript verwenden, um Elemente zu filtern und Stile oder zusätzliche Klassennamen entsprechend anzuwenden. Das Folgende ist beispielsweise eine allgemeine Problemumgehung mit jQuery (vorausgesetzt, es gibt nur eine Zeilengruppe, die mit trElementen in der Tabelle gefüllt ist):

$('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');
});

Mit dem entsprechenden CSS:

table.myClass tr.row.odd {
  ...
}

Wenn Sie automatisierte Testtools wie Selenium verwenden oder HTML mit Tools wie lxml verarbeiten, bieten viele dieser Tools XPath als Alternative:

//table[contains(concat(' ', @class, ' '), ' myClass ')]//tr[contains(concat(' ', @class, ' '), ' row ')][position() mod 2)=1]

Andere Lösungen, die andere Technologien verwenden, werden dem Leser als Übung überlassen. Dies ist nur ein kurzes, erfundenes Beispiel zur Veranschaulichung.


Für das, was es wert ist, gibt es einen Vorschlag für eine Erweiterung der :nth-child()Notation , die zu Selektorstufe 4 hinzugefügt werden soll, um jedes n-te Kind auszuwählen, das einem bestimmten Selektor entspricht. 2

Der Selektor, nach dem Übereinstimmungen gefiltert werden sollen, wird als Argument dafür bereitgestellt :nth-child(), wiederum aufgrund der Art und Weise, wie Selektoren in einer von der vorhandenen Selektorsyntax vorgegebenen Reihenfolge unabhängig voneinander arbeiten. In Ihrem Fall würde es also so aussehen:

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

(Ein aufmerksamer Leser wird bemerken sofort , dass dies sein soll , :nth-child(odd of tr.row)statt, da die einfachen Wähler trund :nth-child()arbeitet unabhängig voneinander als auch. Dies ist eines der Probleme , mit funktionellen Pseudo-Klassen , die Wähler akzeptieren, eine Dose Würmern würde ich Stattdessen nicht in der Mitte dieser Antwort öffnen. Stattdessen gehe ich davon aus, dass die meisten Websites keine anderen Elemente als trElemente als Geschwister voneinander in einem Tabellenkörper haben, wodurch beide Optionen funktional gleichwertig wären.)

Da es sich um einen brandneuen Vorschlag in einer brandneuen Spezifikation handelt, wird dies wahrscheinlich erst einige Jahre später umgesetzt. In der Zwischenzeit müssen Sie wie oben beschrieben ein Skript verwenden.


1 Wenn Sie einen Typ oder einen Universalwähler angeben, muss dieser an erster Stelle stehen. Dies ändert jedoch nichts an der grundsätzlichen Funktionsweise von Selektoren. Es ist nichts weiter als eine syntaktische Eigenart.

2 Dies wurde ursprünglich vorgeschlagen :nth-match(), da es jedoch ab 2014 als Erweiterung des bestehenden Elements neu verwendet wird, da es immer noch ein Element nur relativ zu seinen Geschwistern und nicht zu jedem anderen Element zählt, das dem angegebenen Selektor entspricht :nth-child().

BoltClock
quelle
3
"(Sie werden feststellen, dass ich hier eine ungeordnete Liste verwende, nur um den Punkt nach Hause zu bringen)" Ich wünschte, mehr Menschen wären so überlegt, ob sie geordnete oder ungeordnete Kugeln verwenden. Vielen Dank für Ihre Antwort.
Die rote Erbse
1
@ The Red Pea: Einer meiner größten HTML-Pet-Ärmel: "In der Reihenfolge vom höchsten / niedrigsten zum niedrigsten / höchsten:", gefolgt von einer ungeordneten Liste. Ich meine, komm schon, ernst?
BoltClock
6

Nicht wirklich..

Zitat aus den Dokumenten

Die :nth-childPseudoklasse stimmt mit einem Element überein, vor dem im Dokumentbaum ein + b-1- Geschwister steht , für einen bestimmten positiven oder Nullwert für n, und hat ein übergeordnetes Element.

Es ist ein eigener Selektor und lässt sich nicht mit Klassen kombinieren. In Ihrer Regel muss es nur beide Selektoren gleichzeitig erfüllen, damit die :nth-child(even)Tabellenzeilen angezeigt werden, wenn sie zufällig auch die .rowKlasse haben.

Gabriele Petrioli
quelle
0

nth-of-typefunktioniert nach dem Index des gleichen Elementtyps, nth-childfunktioniert jedoch nur nach dem Index, unabhängig davon, um welche Art von Geschwisterelementen es sich handelt.

Beispielsweise

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

Angenommen, wir möchten im obigen HTML-Code alle Elemente mit der Rest-Klasse ausblenden.

In diesem Fall nth-childund nth-of-typefunktioniert genau so, wie alle Elemente vom gleichen Typ sind, <div>so dass CSS sein sollte

.rest:nth-child(6), .rest:nth-child(7), .rest:nth-child(8), .rest:nth-child(9), .rest:nth-child(10){
    display:none;
}

ODER

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

Jetzt müssen Sie sich fragen, was der Unterschied zwischen nth-childund nth-of-typeso ist der Unterschied

Angenommen, das HTML ist

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

Im obigen HTML-Code unterscheidet sich der .restElementtyp von anderen .restAbsätzen und anderen Teilen. Wenn Sie ihn verwenden nth-child, müssen Sie in diesem Fall so schreiben

.rest:nth-child(6), .rest:nth-child(7), .rest:nth-child(8), .rest:nth-child(9), .rest:nth-child(10){
    display:none;
}

aber wenn Sie n-ten Typ CSS verwenden, kann dies sein

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

Als Art von .restElement ist <p>so hier nth-of-typeerkennt die Art der .restund dann bewarb er sich CSS auf der 1., 2., 3., 4., 5. Element <p>.

Gaurav Aggarwal
quelle
Wie nützlich ist das für <tr>Tags?
Alexis Wilke
0

Möglicherweise können Sie dies mit xpath tun. so etwas //tr[contains(@class, 'row') and position() mod 2 = 0]könnte funktionieren. Es gibt andere SO-Fragen, die die Details zur genaueren Zuordnung von Klassen erweitern.

the8472
quelle
0

Hier ist deine Antwort

<!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>
Pocketninja
quelle
0

Alle Fragen zur Verwendung des n-ten Kindes und zum Überspringen versteckter Tags scheinen als Dupes dieses Tags umzuleiten, daher werde ich dies hier belassen. Ich bin auf diesen Blog gestoßen https://blog.blackbam.at/2015/04/09/css-nth-child-selector-ignore-hidden-element/ , der einen cleveren CSS-Ansatz verwendet, um nth-child dazu zu bringen, versteckte Elemente zu ignorieren. wie folgt:

Das folgende CSS fügt jedem zweiten sichtbaren Element einen rechten Rand hinzu, unabhängig davon, welches Element die cpw-Klasse hat.

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

Hoffe, das hilft jemandem, der der Dupe-Spur folgt, um versteckte Elemente zu ignorieren!

IrishDubGuy
quelle
1
Ich würde dies gerne verbessern, aber es braucht eine funktionierende Demo.
Moob
Ich erinnere mich, dass dies nicht wirklich so robust war, wie es anfangs schien - ich würde jetzt mit dem am besten bewerteten Kommentar gehen, das ist nicht möglich.
IrishDubGuy
0

Wenn Sie für alle Selektoren dieselbe übergeordnete Klasse haben, verwenden Sie diese Klasse, document.querySelector("main .box-value:nth-child(3) select.priorityOption"); da sie in diesem Fall document.querySelector("main .box-value select.priorityOption:nth-child(3)");nicht funktioniert. Danke

<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>
Jatin Aggarwal
quelle