Las pseudo-clases estructurales a fondo

Tal y como prometí en el artículo dedicado a las pseudo-clases, hoy vamos a ampliar el apartado dedicado a las pseudo-clases estructurales, ya que las vimos muy por encima y en cuanto a las fórmulas creo que me quede muy, pero que muy escaso.

En el artículo de hoy vamos a verlas todas de nuevo, aunque mucho más detalladas, y sobre todo nos adentraremos en las fórmulas y todo lo que podemos conseguir con ellas, que por cierto no es poco. Así que no estaría de más que te aprovisionases antes en tu nevera, porque esto comienza ya.

Las fórmulas

Aunque pueda parecer un poco bestia, vamos a entrar directamente con el plato fuerte, las fórmulas. Para ello y aunque no vas a necesitar conocimientos previos sobre ciertas de las pseudo-clases estructurales, aunque sólo sea a nivel de definición, te recomendaría leyeses antes el artículo que le dediqué a las pseudo-clases, para que te hagas una idea global de lo que podemos conseguir con estas expresiones numéricas.

De todas las pseudo-clases estructurales sólo cuatro de ellas admiten una fórmula, y son: :nth-child(N), :nth-last-child(N), :nth-of-type(N) y :nth-last-of-type(N). (N) es el argumento que usan estas pseudo-clases para seleccionar el elemento o elementos a los que aplicarles los estilos, y puede ser una palabra reservada, un número entero, o una expresión numérica del estilo an+b.

La expresión an+b se compone de tres datos. El número a indica cada cuantos elementos queremos contar, el número b por dónde empezar a contar, y en número n actúa como un índice para recorrer los elementos y empieza por cero. Así por ejemplo para una expresión 3n+2, Empezaríamos a contar por el segundo elemento y lo haríamos de tres en tres. En este caso la expresión selecciona el segundo, quinto, octavo, décimo-primero, y así sucesivamente, elementos.

Es importante tener en cuanta que tanto a como b pueden tomar valores negativos, aunque sólo se aplican los valores resultante positivos de N (que es el argumento global). Jugar con valores negativos puede ser muy útil, ya que con sólo valores positivos no abarcamos todas las opciones. Imagínate que queremos seleccionar los cinco primeros elementos de una lista de diez, con valores sólo positivos es imposible, sin embargo aplicando valores negativos es bastante sencillo. La expresión para este caso sería -n+5.

Por último decirte que las fórmulas también se pueden simplificar, supongo que los has notado en el ejemplo anterior con la expresión -n+5 donde he omitido el valor de a. Los casos donde podemos hacer alguna simplificación son:

  • Cuando los valores de a y b con iguales o b es 0. En este caso podemos omitir el valor de b ya que por ejemplo 4n+4 y 4n+0 dan el mismo resultado que 4n. Si no me crees haz el cálculo.
  • Si a es igual a 1 también se puede omitir. Por ejemplo 1n+3 es lo mismo que n+3.
  • Si a es igual a 0, que indica que no vamos a seguir un patrón de repetición, sólo es necesario el valor de b. Por ejemplo 0n+3 es lo mismo que 3.

Lo último que nos queda es ver algún que otro ejemplo práctico, pero eso vamos a ir haciéndolo según detallemos cada pseudo-clase estructural, de ahí el empezar con las fórmulas. Lo que sí vamos a hacer es la estructura HTML con la que vamos a trabajar en los ejemplos, y que no va a ser otra cosa que un par de listas desordenadas y cuatro párrafos, todo ello contenido en un elemento article.


<article>
    <p>Texto 1</p>
    <p>Texto 2</p>
    <ul>
        <li>Objeto 1</li>
        <li>Objeto 2</li>
        <li>Objeto 3</li>
        <li>Objeto 4</li>
    </ul>
    <p>Texto 3</p>
    <p>Texto 4</p>
    <ul>
        <li>Objeto 5</li>
        <li>Objeto 6</li>
        <li>Objeto 7</li>
    </ul>
</article>

:root

La pseudo-clase :root permite seleccionar el elemento padre de mayor nivel dentro del DOM o árbol del documento. En la mayoría de los casos te encontrarás que :root selecciona el elemento html, aunque hay otras posibilidades ya que CSS se puede usar para estilar otro tipo de documentos, como SVG o XML, es cuyo caso el resultado sería diferente.

Sólo hay que tener en cuenta una cosa más, y es que el selector :root tiene una especificidad mayor que el selector html, y en caso de que ambos seleccionen el mismo elemento, :root prevalece sobre html.

:first-child

Esta pseudo-clase nos permite seleccionar un elemento que es el primer elemento contenido dentro de otro elemento, o lo que es lo mismo, el primer elemento hijo contenido en un elemento padre.

Vamos con un ejemplo apoyándonos en la estructura HTML anterior. Los que vamos ha hacer es seleccionar Objeto 1 y Objeto 5, que con esta pseudo-clase es así de sencillo: li:first-child.

:last-child

El selector :last-child selecciona un elemento que es el último elemento contenido dentro de otro elemento.

Como ejemplo vamos ahora a seleccionar los últimos elementos de las dos listas del código HTML, que son Objeto 4 y Objeto 7. El selector que necesitamos para ello es: li:last-child.

:nth-child(N)

La pseudo-clase :nth-child te permite seleccionar uno o varios elementos hijos en función a la posición que ocupan dentro de su padre de acuerdo a una fórmula o expresión numérica. Como ya hemos visto las expresiones numéricas a fondo ahora será más sencillo entender el ejemplo que te pongo a continuación.

Para este ejemplo vamos a cambiar un poco la dinámica, poniendo primero el código y viendo que es lo que estamos seleccionando. El código es el siguiente: p:nth-child(2n+1). Según la fórmula seleccionaremos los párrafos situados en la posición 1, 3, 5, 7, 9, etc. No tenemos tanto elementos, tan sólo 6 (los hijos de article) y no todos ellos son un párrafo.

También hay que tener en cuenta la forma en que se numeran los elementos hijos dentro del padre, del primero al último, quedando así: El primero, Texto 1; el segundo, Texto 2; el tercero, una lista desordenada; el cuarto, Texto 3; el quinto, Texto 4; por último el sexto, que otra vez es una lista desordenada. Por tanto, en este caso estamos seleccionando Texto 1 y Texto 4.

:nth-last-child(N)

No es una pseudo-clase nada compleja si se sabe usar bien :nth-child, ya que funciona exactamente igual salvo que comenzamos a contar desde el último elemento hasta el primero, por tanto los elementos se numeran de forma inversa.

Para este ejemplo no voy a cambiar nada con respecto al usado para :nht-child, para que así veas mejor su funcionamiento. Así que partiendo de la misma fórmula el código a usar es: p:nth-last-child(2n+1) y los párrafos a seleccionar según su posición siguen siendo 1, 3, 5, 7, 9, etc.

Lo único a tener en cuenta es que comenzamos desde el último elemento y terminamos en el primero, con lo cual numeramos de la siguiente forma: El primero, una lista desordenada; el segundo, Texto 4; el tercero, Texto 3; el cuarto, otra lista desordenada; el quinto, Texto 2; y por último Texto 1 que ocupa la sexta posición. Con lo cual estamos seleccionado Texto 3 y Texto 2.

:first-of-type

La pseudo-clase :first-of-type selecciona el primer elemento contenido dentro de otro y que a su vez es de un tipo determinado. Es muy parecido a first-child pero más específico.

Imaginemos que queremos seleccionar la primera de las listas desordenadas que tenemos en el ejemplo. Podríamos hacerlo si conocemos su posición exacta con :nth-child, pero también con :first-of-type y además no es necesario conocer su posición, ya que únicamente queremos seleccionar la primera de todas ellas. El código es así de sencillo: ul:first-of-type.

:last-of-type

Esta pseudo-clase selecciona el último elemento contenido dentro de otro y que a su vez es de un tipo determinado. Al igual que con la anterior pseudo-clase este se parece mucho a :last-child, pero mucho más específica.

Vamos a hacer lo mismo que en el anterior ejemplo, pero en vez de seleccionar la primera lista desordenada vamos a seleccionar la última. También podríamos usar otras pseudo-clases, pero con esta es suficiente. El código el que sigue: ul:last-of-type.

:nth-of-type(N)

La pseudo-clase :nth-of-type(N) selecciona un elemento hijo de un tipo determinado en función a la posición que ocupa dentro de su padre y de acuerdo a la expresión numérica que usemos.

Es muy similar a :nth-child(N) salvo que para la selección del elemento o elementos sólo numeramos aquellos que sean del mismo tipo, y no todos los elementos dentro del padre como ocurría con :nth-child(N).

Así para el ejemplo que estamos usando si aplicamos la misma fórmula que para :nth-child(N) que es 2n+1 y queremos seleccionar los párrafos el código que quedaría sería: p:nth-of-type(2n+1). Hay que tener en cuenta que sólo numeramos los párrafos, por tanto el primer elemento es Texto 1; el segundo, Texto 2; el tercero, Texto 3 y el cuarto, Texto 4. Por tanto y según este código de ejemplo estamos seleccionando Texto 1 y Texto 3.

:nth-last-of-type(N)

Esta es una pseudo-clase muy sencilla de dominar si conocemos bien :nth-of-type(N), ya que la única diferencia radica en que comenzamos a contar desde el último elemento del mismo tipo hasta el primero, por tanto los elementos se numeran de forma inversa.

Para este ejemplo vamos a usar la mista fórmula que usamos en el anterior, para ver mejor las diferencias. El código que vamos a usar es: p:nth-last-of-type(2n+1) y la numeración a tener en cuenta es: el primer elemento es Texto 4; el segundo, Texto 3; el tercero, Texto 2 y el cuarto, Texto 1. Como supongo ya has deducido los elementos que seleccionamos son Texto 4 y Texto 2.

Y hasta aquí ha llegado este artículo dedicado a las pseudo-clases estructurales, donde espero haber aclarado un poco su funcionamiento y también como se manejan las dichosas formulitas. También aprovecho para aconsejarte :nth Tester, una aplicación de CSS-Tricks, donde podrás trastear con las pesudo-clases del tipo :nth y sus fórmulas.