Questo è un problema molto comune che si verifica a causa di un fraintendimento di come funzionano :nth-child()
e :nth-of-type()
. Sfortunatamente, al momento non esiste ancora una soluzione basata su selettori perché i selettori non forniscono un modo per far corrispondere l'ennesimo figlio che corrisponde a un selettore arbitrario basato su un modello come numero dispari, pari o qualsiasi e b != 0
. Ciò va oltre i soli selettori di classe, per attribuire selettori, negazioni e combinazioni più complesse di selettori semplici.
Il :nth-child()
pseudo-class conta elementi tra tutti i dei loro fratelli sotto lo stesso genitore. Non conta solo i fratelli che corrispondono al resto del selettore. Allo stesso modo, lo :nth-of-type()
pseudo-class conta i fratelli che condividono lo stesso tipo di elemento, che si riferisce al nome del tag in HTML e non al resto del selettore.
Questo significa anche che se tutti i figli della stessa madre sono dello stesso tipo di elemento, ad esempio nel caso di un corpo tabella cui solo i bambini sono tr
elementi o un elemento della lista di cui solo i bambini sono li
elementi, allora :nth-child()
e :nth-of-type()
si comportano in modo identico, ovvero per ogni valore di an+b
, :nth-child(an+b)
e :nth-of-type(an+b)
corrisponderanno allo stesso insieme di elementi.
Infatti, tutti i selettori semplici in un dato selettore composto, tra pseudo-classi come :nth-child()
e :not()
, lavoro indipendentemente l'uno dall'altro, piuttosto che guardando la sottoinsieme di elementi che è compensato dal resto del selezionatore.
Ciò implica anche che non v'è alcuna nozione di ordine fra selettori semplici all'interno di ogni singola selettore composto , il che significa per esempio i seguenti due selettori sono equivalenti:
table.myClass tr.row:nth-child(odd)
table.myClass tr:nth-child(odd).row
tradotta, entrambi significano:
Selezionare qualsiasi elemento tr
che corrisponde tutte le seguenti condizioni indipendenti:
- è un figlio dispari del suo genitore;
- ha la classe "riga"; e
- è un discendente di un elemento
table
che ha la classe "myClass".
(noterete il mio uso di una lista non ordinata qui, giusto per guidare il punto a casa)
Poiché non v'è attualmente nessuna soluzione CSS puro, si dovrà utilizzare un script per filtrare gli elementi e applicare gli stili o nomi di classi extra di conseguenza. Ad esempio, la seguente è una soluzione comune utilizzando jQuery (supponendo che c'è solo gruppo una riga popolato con tr
elementi all'interno della tabella):
$('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');
});
Con il corrispondente CSS:
table.myClass tr.row.odd {
...
}
Se' re utilizzando strumenti di test automatizzati come selenio o elaborazione HTML con strumenti come lxml, molti di questi strumenti consentono XPath come alternativa:
//table[contains(concat(' ', @class, ' '), ' myClass ')]//tr[contains(concat(' ', @class, ' '), ' row ')][position() mod 2)=1]
Altro sol le utenze che utilizzano diverse tecnologie vengono lasciate come esercizio al lettore; questo è solo un breve esempio di illustrazione.
Per quel che vale, c'è una proposta di an extension to the :nth-child()
notation da aggiungere al livello di selettori 4 per lo scopo specifico di selezionare ogni bambino ennesima corrispondenza di un determinato selettore.
Il selettore con cui filtrare corrispondenze viene fornito come argomento :nth-child()
, sempre per quanto selettori operano indipendentemente l'uno dall'altro in una sequenza come dettato dalla sintassi selettore esistente. Quindi nel tuo caso, sarebbe simile a questa:
table.myClass tr:nth-child(odd of .row)
(Un lettore attento noterà subito che questo dovrebbe essere :nth-child(odd of tr.row)
invece, dal momento che i selettori semplici tr
e :nth-child()
operano in modo indipendente l'uno dall'altro, come pure questo. è uno dei problemi con le pseudo-classi funzionali che accettano i selettori, una lattina di worm che preferirei non aprire nel mezzo di questa risposta, ma intendo dire che la maggior parte dei siti non avrà altri elementi di tr
elementi come fratelli l'uno dell'altro nel corpo di una tabella, il che renderebbe entrambe le opzioni equivalenti dal punto di vista funzionale.)
Naturalmente, essendo una proposta nuova di zecca in una nuova specifica, questo probabilmente non vedrà l'implementazione fino a pochi anni lungo la strada. Nel frattempo, dovrai continuare ad usare uno script, come sopra.
Se si specifica un tipo o selettore universale, che deve venire prima. Questo non cambia il modo in cui i selezionatori lavorano fondamentalmente, comunque; non è altro che una stranezza sintattica.
Questo è stato originariamente proposto come :nth-match()
questo, perché conta ancora un elemento relativamente solo ai suoi fratelli, e non ad ogni altro elemento che corrisponde alla data selettore, allora è dal 2014 stato riproposto come un'estensione al :nth-child()
esistente invece.
"(noterete il mio uso di una lista non ordinata qui, solo per spingere il punto a casa)" Vorrei che più persone fossero consapevoli del loro uso di proiettili ordinati e non ordinati. La ringrazio per la risposta. –
@ The Red Pea: uno dei miei più grandi animaletti HTML: "In ordine dal più alto/più basso al più basso/più alto:" seguito da un elenco non ordinato. Voglio dire, dai, sul serio? – BoltClock