2011-04-04 1 views
62

C'è un modo per selezionare ogni bambino n. che corrisponde (o non corrisponde) a un selettore arbitrario? Ad esempio, voglio selezionare ogni riga della tabella strano, ma all'interno di un sottoinsieme delle righe:Posso combinare: nth-child() o: nth-of-type() con un selettore arbitrario?

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> 

Ma :nth-child() sembra solo per contare tutti gli elementi tr indipendentemente dal fatto o meno che siano del classe "riga", così finisco con quello anche "riga" elemento invece dei due che sto cercando. La stessa cosa succede con :nth-of-type().

Qualcuno può spiegare perché?

risposta

83

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.

+3

"(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. –

+1

@ 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

5

Non proprio ..

quote from the docs

Il :nth-child pseudo-classe corrisponde a un elemento che ha un + B-1 fratelli prima che nell'albero del documento, per un determinato valore positivo o zero per n, e ha un elemento padre.

È un selettore a sé stante e non si combina con le classi. Nella tua regola, deve solo soddisfare entrambi i selettori contemporaneamente, quindi mostrerà le righe della tabella :nth-child(even) se hanno anche la classe .row.

0

nth-of-type funziona in base all'indice dello stesso tipo dell'elemento ma nth-child funziona solo in base all'indice, indipendentemente dal tipo di elementi fratelli.

Per esempio

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

Supponiamo al precedente html vogliamo nascondere tutti gli elementi che hanno codice categoria di riposo.

In questo caso nth-child e nth-of-type funzionerà esattamente uguale a tutti gli elementi sono dello stesso tipo che è <div> così css dovrebbe essere

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

O

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

ora si deve ti starai chiedendo quale sia la differenza tra nth-child e nth-of-type quindi questa è la differenza

Supponiamo che l'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> 

nel codice HTML sopra il tipo di .rest elemento è diverso dagli altri .rest sono paragrafi e altri sono div quindi in questo caso, se si utilizza nth-child devi scrivere come questo

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

ma se si utilizza nth-of-type css può essere questo

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

Come tipo di elemento è .rest<p> ecco nth-of-type rileva il tipo di .rest e poi ha applicato css al 1 °, 2 °, 3 °, 4 °, 5 ° elemento di <p>.

+0

Quanto è utile per i tag ''? –

0

Potrebbe essere possibile farlo con xpath. qualcosa come //tr[contains(@class, 'row') and position() mod 2 = 0] potrebbe funzionare. Ci sono altre domande SO che espandono i dettagli su come abbinare le classi in modo più preciso.