jQuery / Selector / :nth-child() - Seleccionar posiciones an+b
En jQuery, :nth-child(an+b) selecciona elementos hermanos en posiciones que cumplen una fórmula, contando desde uno dentro de cada padre. p:nth-child(2) significa un p que es el segundo hijo de tipo elemento, no el segundo p. Usa :nth-of-type(2) para el segundo hermano p, o .eq(1) para el segundo elemento de un conjunto ya seleccionado.
Contar desde uno e incluir otras etiquetas
La documentación de :nth-child() sigue las reglas CSS de posición entre hermanos. El recuento empieza de nuevo para cada padre e incluye otras etiquetas. Los espacios de texto y comentarios no son elementos. Los elementos ocultos conservan su posición mientras permanezcan en el documento, así que el orden visible no basta.
Si un padre contiene h2, p, p, p:nth-child(1) queda vacío y p:nth-child(2) elige el primer p. No reúne primero los p para numerarlos después. Limita el ámbito a hijos directos con >, como en el ejemplo.
Interpretar an+b y fórmulas habituales
En la definición CSS de an+b, a y b son enteros y n toma enteros no negativos como 0, 1 y 2. Solo coinciden las posiciones positivas resultantes. Cero y las posiciones negativas no seleccionan nada. -n+3 produce 3, 2, 1, las primeras tres posiciones; no cuenta hacia atrás desde el final.
| Condición | Posiciones | Significado |
|---|---|---|
| 2 | 2 | Segundo elemento de cada padre |
| 2n o even | 2, 4, 6, … | Posiciones pares |
| 2n+1 u odd | 1, 3, 5, … | Posiciones impares |
| 3n+1 | 1, 4, 7, … | Cada tercera posición desde uno |
| -n+3 | 1, 2, 3 | Primeras tres posiciones |
Añadir p delante de la condición conserva solo los p en esas posiciones. Si el cuarto hijo es span, p:nth-child(2n) lo excluye, pero no lo salta para renumerar como cuarto un p posterior.
Ejemplo completo con etiquetas mezcladas
Guarda todo el código en UTF-8 como nth-child-demo.html y ábrelo en un navegador. No necesitas instalar nada, pero sí internet para cargar el archivo oficial de jQuery desde su red de distribución de contenidos, o CDN. El código usa 4.0.0; las fórmulas, inserción, restablecimiento y comparación se ejecutaron con 3.7.1 y 4.0.0.
A contiene h2, p, p, span, p; B contiene h2, p, p, p. El resultado muestra los identificadores de los p para compararlos con las posiciones de las etiquetas.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Sibling positions and formulas</title>
<style>
body { font: 16px/1.6 sans-serif; margin: 24px; }
.group { border: 1px solid #aaa; padding: 12px; margin: 12px 0; }
.group > * { display: block; margin: 6px 0; padding: 6px; }
.group > .marked { background: #fff0b3; outline: 2px solid #b56b00; }
button, select { padding: 8px; margin: 4px; }
</style>
<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
</head>
<body>
<h1>Sibling positions and formulas</h1>
<div id="groups">
<section class="group" id="group-a">
<h2>A heading</h2>
<p id="a1">A paragraph 1</p>
<p id="a2">A paragraph 2</p>
<span>A note</span>
<p id="a3">A paragraph 3</p>
</section>
<section class="group" id="group-b">
<h2>B heading</h2>
<p id="b1">B paragraph 1</p>
<p id="b2">B paragraph 2</p>
<p id="b3">B paragraph 3</p>
</section>
</div>
<label for="rule">Formula:</label>
<select id="rule">
<option value="2">2</option>
<option value="2n">2n (even)</option>
<option value="2n+1">2n+1 (odd)</option>
<option value="3n+1">3n+1</option>
<option value="-n+3">-n+3</option>
</select>
<button type="button" id="prepend">Prepend notice to A</button>
<button type="button" id="reset">Reset</button>
<output id="result" aria-live="polite"></output>
<script>
$(function () {
function refresh() {
$("#groups > .group > p").removeClass("marked");
const rule = $("#rule").val();
const $chosen = $("#groups > .group > p:nth-child(" + rule + ")");
$chosen.addClass("marked");
const ids = $chosen.map((_, item) => item.id).get().join(", ");
$("#result").text(`${ids || "none"} | ${$chosen.length}`);
}
$("#rule").on("change", refresh);
$("#prepend").on("click", function () {
if (!$("#extra").length) {
$("#group-a").prepend('<div id="extra">Notice</div>');
}
refresh();
});
$("#reset").on("click", function () {
$("#extra").remove();
$("#rule").val("2");
refresh();
});
refresh();
});
</script>
</body>
</html>
La fórmula inicial es 2. El segundo elemento de cada grupo es su primer p: se resaltan a1 y b1.
a1, b1 | 2
- 2n produce
a1, b1, b3 | 3. El cuarto elemento de A es span y no cumple p. - 2n+1 produce
a2, a3, b2 | 3. El h2 inicial queda excluido. - 3n+1 produce
b3 | 1. Las posiciones 1 y 4 de A son h2 y span; solo la cuarta de B es p. - -n+3 produce
a1, a2, b1, b2 | 4: los p entre los primeros tres hijos de tipo elemento de cada padre. - Pulsa Reset y después Prepend notice to A. El div insertado al principio convierte h2 en el segundo hijo de A. Con fórmula 2 queda
b1 | 1. Las pulsaciones repetidas no crean duplicados. - Reset elimina solo el div añadido, restaura la fórmula 2 y consulta otra vez. Vuelven el contenido original y
a1, b1 | 2.
Comparar :nth-of-type() y .eq()
Tras Reset, ejecuta este fragmento en la consola de desarrollo. :nth-of-type() cuenta hermanos de la misma etiqueta; .eq() cuenta desde cero el conjunto ya seleccionado.
const ids = $set => $set.map((_, item) => item.id).get().join(", ");
console.log(ids($("#groups > .group > p:nth-child(2)")));
console.log(ids($("#groups > .group > p:nth-of-type(2)")));
console.log(ids($("#groups > .group > p").eq(1)));
a1, b1
a2, b2
a2
La primera línea devuelve a1 y b1, segundos hijos de tipo elemento que son p. La segunda devuelve a2 y b2, segundos p de cada padre. La última devuelve solo a2, en el índice 1 del conjunto total de p. Un índice negativo de .eq() cuenta desde el final del conjunto y difiere de -n+3.
Documento dinámico y resultados inesperados
Las selecciones no reflejan automáticamente los cambios del documento. Un conjunto con a1 y b1 guardado antes de insertar mantiene esos elementos después. Consulta de nuevo, como refresh, y elimina las marcas anteriores para reflejar posiciones actuales.
Si queda vacío, revisa posiciones cero o inexistentes, la etiqueta real y los títulos, avisos o elementos ocultos intermedios. En tablas, inspecciona también padres intermedios como tbody en el modelo de objetos del documento, DOM. Si no responde, comprueba primero la carga de jQuery en Network y los errores en Console.




