2011-04-04 16 views
62

¿Hay alguna manera de seleccionar cada enésimo hijo que coincida (o no coincida) con un selector arbitrario? Por ejemplo, quiero seleccionar cada fila de la tabla extraño, pero dentro de un subconjunto de las filas:¿Puedo combinar: nth-child() o: nth-of-type() con un selector 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> 

Pero :nth-child() sólo parece contar todos los elementos tr independientemente de si están o no de la clase "row", así que termino con el elemento even "fila" en lugar de los dos que estoy buscando. Lo mismo ocurre con :nth-of-type().

¿Alguien puede explicar por qué?

Respuesta

83

Este es un problema muy común que surge debido a un malentendido sobre cómo funcionan :nth-child() y :nth-of-type(). Desafortunadamente, actualmente no hay una solución basada en selector porque Selectores no proporciona una forma de coincidir con el enésimo hijo que coincide con un selector arbitrario basado en un patrón como números impares, pares o cualquier an+b donde a != 1 y b != 0. Esto se extiende más allá de los selectores de clase, para atribuir selectores, negaciones y combinaciones más complejas de selectores simples.

:nth-child() pseudo-class cuenta elementos entre todos de sus hermanos bajo el mismo padre. No cuenta solo los hermanos que coinciden con el resto del selector. Del mismo modo, el :nth-of-type() pseudo-class cuenta hermanos que comparten el mismo tipo de elemento, que se refiere al nombre de la etiqueta en HTML, y no al resto del selector.

Esto también significa que si todos los elementos secundarios del mismo elemento son del mismo tipo de elemento, por ejemplo en el caso de un cuerpo de tabla cuyos elementos únicos son tr o un elemento de lista cuyos elementos secundarios únicos son li, :nth-child() y :nth-of-type() se comportarán de manera idéntica, es decir, para cada valor de an+b, :nth-child(an+b) y :nth-of-type(an+b) coincidirá con el mismo conjunto de elementos.

De hecho, todos los selectores simples en un selector compuesto dado, incluyendo pseudo-clases tales como :nth-child() y :not(), trabajo independientemente uno de otro, en vez de buscar la subconjunto de elementos que se corresponde con el resto del selector.

Esto también implica que no hay noción de orden entre selectores simples dentro de cada selector compuesto individual , lo que significa, por ejemplo, las siguientes dos selectores son equivalentes:

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

Traducido al Inglés, ambos significan:

Seleccione cualquier elemento tr que coincide con todas las siguientes condiciones independientes:

  • es un hijo con número impar de su padre;
  • tiene la clase "fila"; y
  • es un descendiente de un elemento table que tiene la clase "myClass".

(usted notará mi uso de una lista desordenada aquí, sólo para remachar el clavo)

Debido a que actualmente no existe una solución CSS puro, que tendrá que utilizar una secuencia de comandos para filtrar elementos y aplicar estilos o nombres de clase adicionales en consecuencia. Por ejemplo, la siguiente es una solución común usando jQuery (suponiendo que sólo hay grupo una fila poblado con tr elementos dentro de la tabla):

$('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 el CSS correspondiente:

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

Si' re el uso de herramientas de test como el selenio o el procesamiento de HTML con herramientas como lxml, muchas de estas herramientas permiten XPath como alternativa:

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

Otro sol Las aplicaciones que usan diferentes tecnologías se dejan como un ejercicio para el lector; esto es solo un ejemplo breve y artificial para la ilustración.


Por lo que vale la pena, no es una propuesta de an extension to the :nth-child() notation que se añade a nivel de selectores 4 para el propósito específico de la selección de todos los niños enésimo juego un selector dado.

El selector por el que filtrar partidos se proporciona como un argumento a :nth-child(), de nuevo debido a cómo selectores operan independientemente uno de otro en una secuencia según lo dictado por la sintaxis selector existente. Así, en su caso, se vería así:

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

(Un lector astuto se tenga en cuenta de inmediato que esto debería ser :nth-child(odd of tr.row) lugar, ya que los selectores simples tr y :nth-child() operan independientemente unos de otros, así Este. es uno de los problemas con las pseudo-clases funcionales que aceptan selectores, una lata de gusanos que prefiero no abrir en el medio de esta respuesta. En cambio, voy a suponer que la mayoría de los sitios no tendrán ningún otro elemento que tr elementos como hermanos entre sí en un cuerpo de tabla, lo que haría que cualquiera de las opciones sea funcionalmente equivalente.)

Por supuesto, al tratarse de una nueva propuesta en una nueva especificación, probablemente no se implementará hasta dentro de unos años. Mientras tanto, tendrás que seguir usando un script, como se indica arriba.


Si especifica un tipo o del selector universal, debe ser lo primero. Sin embargo, esto no cambia la forma en que funcionan los selectores; no es más que una peculiaridad sintáctica.

Esto fue propuesto originalmente como :nth-match(), sin embargo, ya que aún cuenta un elemento relativo sólo a sus hermanos, y no a cualquier otro elemento que coincide con el selector dado, se ha puesto a partir de 2014 ha reutilizado como una extensión a la existente :nth-child() en su lugar.

+3

"(notará el uso de una lista desordenada aquí, solo para aclarar el punto)" Desearía que hubiera más gente deliberadamente sobre el uso de viñetas ordenadas y no ordenadas. Gracias por su respuesta. –

+1

@The Red Pea: Una de mis mayores preocupaciones con HTML: "En orden de mayor/menor a menor/más alta:" seguida de una lista desordenada. Quiero decir, ¿en serio? – BoltClock

5

En realidad no ..

quote from the docs

La pseudo-clase :nth-child coincide con un elemento que tiene un + b-1 hermanos antes de que en la estructura del documento, para un determinado valor positivo o cero para n, y tiene un elemento padre.

Es un selector propio y no se combina con las clases. En su regla solo tiene que satisfacer a ambos selectores al mismo tiempo, por lo que mostrará las filas de la tabla :nth-child(even) si también tienen la clase .row.

0

nth-of-type funciona de acuerdo con el índice del mismo tipo del elemento pero nth-child funciona solo según el índice sin importar qué tipo de hermanos sean los elementos.

Por ejemplo

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

Supongamos que en HTML anterior queremos ocultar todos los elementos que tienen la clase de descanso.

En este caso nth-child y nth-of-type funcionará exactamente igual que todos los elementos son del mismo tipo que es <div> por lo CSS debe ser

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

Ahora usted debe se pregunta cuál es la diferencia entre nth-child y nth-of-type así que esta es la diferencia

Supongamos que el HTML es

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

En el html por encima del tipo de .rest elemento es diferente de los demás .rest se párrafos y otros están Divisiones por lo que en este caso si se utiliza nth-child usted tiene que escribir como esto

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

pero si se utiliza enésimo-de-tipo CSS puede ser esto

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

Como .rest tipo de elemento es <p> así que aquí nth-of-type es detectar el tipo de .rest y luego se aplica css en el primero, segundo, tercero, cuarto, quinto elemento de <p>.

+0

¿Qué tan útil es eso para las etiquetas ''? –

0

Puede hacer eso con xpath. algo como //tr[contains(@class, 'row') and position() mod 2 = 0] podría funcionar. Hay otras preguntas de SO que amplían los detalles sobre cómo hacer coincidir las clases de forma más precisa.

Cuestiones relacionadas