¿Puedo combinar:nth-child () o: nth-of-type () con un selector arbitrario?


¿Hay una 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 impar, pero dentro de un subconjunto de las filas:

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() simplemente parece contar todos los elementos tr independientemente de si son o no de la clase "row", así que termino con el elemento one even "row" en lugar de los dos que estoy buscando. Lo mismo sucede con :nth-of-type().

Puede alguien explicar ¿Por qué?

Author: BoltClock, 2011-04-05

4 answers

Este es un problema muy común que surge debido a un malentendido de cómo funcionan :nth-child() y :nth-of-type(). Desafortunadamente, actualmente no hay una solución basada en selectores por el momento porque Selectors no proporciona una forma de emparejar el enésimo hijo que coincida 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 solo selectores de clase, a selectores de atributos, negaciones y combinaciones más complejas de selector.

El :nth-child() la pseudo-clase 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() la pseudo-clase 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 hijos del mismo padre son del mismo tipo de elemento, por ejemplo en el caso de un cuerpo de tabla cuyos únicos hijos son elementos tr o un elemento de lista cuyos únicos hijos son elementos li, entonces :nth-child() y :nth-of-type() se comportarán de forma 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 como :nth-child() y :not(), funcionan independientementeel uno del otro, en lugar de mirar el subconjunto de elementos que coinciden por el resto del selector.

Esto también implica que no hay noción de orden entre selectores simples dentro de cada selector compuesto individual1, lo que significa, por ejemplo, que los 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 coincida con todas las siguientes condiciones independientes:

  • es un hijo impar de su padre;{[63]]}
  • tiene la clase "row"; y
  • es un descendiente de un elemento table que tiene la clase "MyClass".

(te darás cuenta de mi uso de una lista desordenada aquí, solo para llevar el punto a casa)

Debido a que actualmente no hay una solución CSS pura, tendrá que usar un script 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 solo hay un grupo de filas rellenado 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 está utilizando herramientas de prueba automatizadas como Selenium o procesando 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]

Otras soluciones que utilizan diferentes tecnologías se dejan como un ejercicio para el lector; esto es solo un breve ejemplo artificial para la ilustración.


Por si sirve de algo, hay una propuesta para una extensión de la notación :nth-child() que se agregará a los Selectores de nivel 4 con el propósito específico de seleccionar cada enésimo hijo que coincida con un selector dado.2

El selector por el cual filtrar coincidencias se proporciona como un argumento a :nth-child(), de nuevo debido a cómo los selectores operan independientemente unos de otros en una secuencia como lo dicta la sintaxis del selector existente. Así que en su caso, se vería así:

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

(Un lector astuto notará de inmediato que esto debería ser :nth-child(odd of tr.row) en su lugar, ya que los selectores simples tr y :nth-child() operan independientemente el uno del otro también. Este es uno de los problemas con las pseudo-clases funcionales que aceptan selectores, una lata de gusanos que preferiría no abrir en medio de esta respuesta. En su lugar, voy a ir con la suposición de 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 funcionalmente equivalente.)

De por supuesto, al ser una propuesta completamente nueva en una especificación completamente nueva, esto probablemente no se implementará hasta unos pocos años más adelante. Mientras tanto, usted tendrá que seguir con el uso de un script, como anteriormente.


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

2Esto fue propuesto originalmente como :nth-match(), sin embargo, debido a que todavía cuenta un elemento relativo solo a sus hermanos, y no a todos los demás elementos que coinciden con el selector dado, desde 2014 se ha reutilizado como una extensión del :nth-child() existente en su lugar.

 98
Author: BoltClock,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-11-09 04:06:10

En realidad no..

Cita de los documentos

La pseudo-clase :nth-child coincide con una elemento que tiene un + b-1 hermanos antes de que en el árbol de documentos , para un dado valor positivo o cero para n, y tiene un elemento padre.

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

 5
Author: Gabriele Petrioli,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-20 09:24:06

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

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 el html anterior queremos ocultar todos los elementos que tienen clase rest.

En este caso nth-child y nth-of-type funcionarán exactamente igual que todos los elementos son del mismo tipo que es <div> por lo que 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 ser preguntándose cuál es la diferencia entre nth-child y {[6] } 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 anterior, el tipo de elemento .rest es diferente de otros .rest son párrafos y otros son div, por lo que en este caso si usa nth-child debe escribir así

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

Pero si usas nth-of-type css puede ser este

.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 el tipo de elemento .rest es <p> así que aquí nth-of-type está detectando el tipo de .rest y luego aplicó css en el 1er, 2do, 3er, 4to, 5to elemento de <p>.

 0
Author: Gaurav Aggarwal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-04 10:41:42

Es posible que pueda hacerlo con xpath. algo como //tr[contains(@class, 'row') and position() mod 2 = 0] podría funcionar. Hay otras preguntas que amplían los detalles sobre cómo hacer coincidir las clases con mayor precisión.

 0
Author: the8472,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-11-04 23:27:07