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+b
Wo a != 1
und 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 tr
Elemente Elemente sind , oder eines Listenelements, dessen einzige untergeordnete li
Elemente 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 tr
Element 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
table
Elements 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 tr
Elementen 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 tr
und :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 tr
Elemente 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()
.