Pseudo-elementos y pseudo-selectores en CSS

Publicada en WordPress.

Mira nuestro vídeo

Existe una versión mejor de tu web

Comparte este artículo

Cada vez que en Nelio tenemos que tocar algún estilo CSS de la web, Toni y yo jugamos al piedra-papel-tijeras para ver cuál es el «afortunado» al que le toca la tarea. Y es que, durante muchos años, maquetar páginas web usando CSS y HTML era un auténtico suplicio y rara era la vez que, arreglando un detallito en una parte de tu web, no rompías mil cosas en otros lados.

Uno no puede más que admirar y maravillarse ante la labor de los front-end developers.

Pero la verdad es que CSS ha cambiado muchísimo en los últimos años y, si aprovechas todo su potencial, así como sus nuevas funcionalidades, es mucho más fácil maquetar y estilar tu página web. En mi opinión, dos de los grandes avances en CSS han llegado gracias a la inclusión, primero, de flex (para maquetar filas y columnas) y, un poco después, grid (para maquetar parrillas).

CSS está lleno de pijaditas que pueden simplificar tu trabajo. Y hoy vamos a ver dos de ellas: los pseudo-elementos y los pseudo-selectores en CSS.

Cómo crear contenido con los pseudo-elementos de CSS

Los pseudo-elementos en CSS son un mecanismo para acceder a partes del HTML que no tienen asociado un nodo en el DOM. Por ejemplo, está claro que una «parte de nuestro documento» podría ser «la primera línea de un párrafo», «la primera letra de un párrafo» o «la selección que ha hecho el usuario». Pero los pseudo-elementos también son una forma de crear contenido antes o después de un elemento de nuestro DOM a través de CSS.

Los pseudo-elementos disponibles en CSS3 son:

  • ::before: sirve para añadir contenido antes de un elemento
  • ::after: sirve para añadir contenido después de un elemento
  • ::first-letter: selecciona la primera letra de un elemento de tipo «bloque» (es decir, los que tienen como display valores tipo block, inline-block, table-cell, etc)
  • ::first-line: selecciona la primera línea de un elemento que, como en el caso anterior, sea de tipo «bloque»
  • ::selection: hace referencia a las partes del documento que el visitante haya seleccionado

Como puedes ver, los pseudo-elementos se caracterizan por empezar con un par de dos puntos (::). La forma de usarlos es extremadamente sencilla.

Seleccionando partes del contenido

Supón, por ejemplo, que queremos que un cierto párrafo tenga la primera línea en naranja y subrayado. Pues basta con hacer algo tal que así:

p::first-line {
  color: orange;
  text-decoration: underline;
}

y conseguiremos el resultado deseado:

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum mollis leo in turpis interdum, at pharetra velit elementum. Nam eget lacus sed lacus dictum scelerisque. Proin porta ligula sed mi semper, vel interdum massa auctor. Pellentesque et massa congue, tincidunt erat ac, tincidunt elit. Sed ac dolor metus. Nam commodo metus sed ligula consectetur interdum. Curabitur odio est, tempor id egestas nec, aliquam at nisl.

En el caso de la selección, por ejemplo, el número de propiedades CSS que podemos manipular está limitada a color, background, cursor y outline, pero nos permite seleccionar una paleta de colores acorde a nuestra web:

p::selection {
  background: #21acde;
  color: white;
}

y cuyo resultado puedes ver si seleccionas el texto que hay a continuación:

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum mollis leo in turpis interdum, at pharetra velit elementum. Nam eget lacus sed lacus dictum scelerisque. Proin porta ligula sed mi semper, vel interdum massa auctor. Pellentesque et massa congue, tincidunt erat ac, tincidunt elit. Sed ac dolor metus. Nam commodo metus sed ligula consectetur interdum. Curabitur odio est, tempor id egestas nec, aliquam at nisl.

Creando nuevo contenido

También tienes la opción de añadir contenido dinámicamente a tu página. Por ejemplo, imagina que tienes una lista de elementos tal que así:

<ul>
  <li>Uno</li>
  <li>Dos</li>
  <li>Tres</li>
</ul>

En lugar de mostrarla como siempre:

  • Uno
  • Dos
  • Tres

puedes mostrarlo como un párrafo en que cada elemento está separado del siguiente con una barra vertical de color azul:

  • Uno
  • Dos
  • Tres

usando el pseudo-elemento ::after en cada ítem de la lista:

ul li {
  display: inline;
}

  ul li::after {
    color: #21acde;
    content: " | ";
    display: inline-block;
  }

La verdad es que con los pseudo-elementos ::before y ::after se pueden hacer muchas virguerías: combinar múltiples fondos en un único elemento, mostrar las URLs de los enlaces cuando se imprime la página, ordenar los elementos flotantes, etiquetar bloques, embellecer tu tipografía, etc.

Mejora tu puntería a la hora de aplicar estilos usando pseudo-clases

Las pseudo-clases de CSS nos permiten seleccionar elementos de nuestra web que, o bien están en un estado concreto, o bien tienen alguna propiedad especial que los hace especiales (valga la redundancia). El ejemplo más habitual (y antiguo) son, probablemente, las pseudo-clases de los enlaces:

  • a:link son todos los enlaces que no se han visitado aún
  • a:visited son todos aquellos enlaces que se han visitado
  • a:hover es cualquier enlace que tenga el ratón encima
  • a:focus es similar al anterior, pero en lugar de fijarse si el enlace tiene el raton encima, se fija en si el enlace tiene «el foco» (lo que se consigue usando el teclado saltando de un elemento a otro con la tecla tab)
  • a:active aparece cuando el usuario hace clic en el enlace

En CSS hay alrededor de unas 60 pseudo-clases. Una gran mayoría de ellas te permiten filtrar los elementos según su estado (por ejemplo, puedes seleccionar elementos de solo-lectura usando :read-only), pero hay algunas «excepciones» especialmente interesantes.

Por cierto, fíjate que puedes distinguir una pseudo-clase de un pseudo-elemento CSS porque las primeras empiezan con un único símbolo de dos-puntos (:) en lugar de con dos (::).

Seleccionando los hijos de un elemento con las pseudo-clases «child» y «of-type»

¿Recuerdas el ejemplo que hemos visto anteriormente en el que añadíamos una barra vertical para separar los elementos de una lista? Pues, si te fijas bien, verás que la regla que pusimos no acaba de funcionar:

  • Uno
  • Dos
  • Tres

porque el último elemento también incluye esa barra después, aunque no debería. Pues bien, si pudiéramos seleccionar «el último elemento de la lista», tendríamos una forma de quitarle la barra, ¿no? Pues vamos a hacer precisamente eso:

ul li {
  display: inline;
}

  ul li::after {
    color: #21acde;
    content: " | ";
    display: inline-block;
  }

    ul li:last-child::after {
      display: none;
    }

y el resultado es:

  • Uno
  • Dos
  • Tres

Como ves, lo único que estamos haciendo es añadir una nueva regla usando la pseudo-clase :last-child, la cual nos permite seleccionar el último elemento li de nuestra lista ul y, una vez lo tenemos, ocultar su pseudo-elemento ::after con un display: none.

Particularidades de *-child y *-of-type

Existen tres variaciones de la pseudo-clase *-child:

  • :first-child permite seleccionar el primer hijo de un elemento
  • :last-child hace lo propio con el último hijo
  • :nth-child(i) permite seleccionar i-ésimo hijo de un elemento (por ejemplo, :nth-child(2) es el segundo hijo)

Supón el siguiente CSS:

li strong:first-child {
  color: orange;
  text-decoration: underline;
}

y el siguiente código HTML:

<ol>
  <li>Lorem <strong>ipsum</strong> dolor <strong>sit</strong> amet.</li>
  <li><em>Lorem</em> <strong>ipsum</strong> dolor <strong>sit</strong> amet.</li>
  <li>Lorem <strong>ipsum</strong> dolor <em><strong>sit</strong></em> amet.</li>
</ol>

¿Qué crees que pasará? En principio, da la sensación que en los tres casos, la palabra ipsum aparecerá subrayada y de color naranja, porque es el primer hijo strong, ¿no? Veamos:

  1. Lorem ipsum dolor sit amet.
  2. Lorem ipsum dolor sit amet.
  3. Lorem ipsum dolor sit amet.

¡Vaya! Pues parece que no… ¿qué ha pasado?

La pseudo-clase :first-child sirve para especificar una propiedad del nodo al que aplica: que sea el primer hijo de su padre. En la primera frase, ipsum es la primera palabra en negrita. En la segunda frase, el primer nodo hijo es em con la palabra Lorem, luego la negrita de ipsum no se ve afectada por nuestra regla. Y en la tercera frase, las dos negritas son «los primeros hijos de sus respectivos padres»: ipsum es hijo de li y sit es hijo de la etiqueta em.

Si lo que queríamos hacer era subrayar y pintar de color naranja la primera etiqueta strong de cada nodo li, lo que teníamos que hacer es lo siguiente:

li > strong:first-of-type {
  color: orange;
  text-decoration: underline;
}

Es decir, especificamos que solo nos interesan aquellas etiquetas strong que sean hijas directas de la etiqueta li y, de todas las etiquetas de tipo strong que sean hijas de li, solo nos interesa la primera de ese tipo:

  1. Lorem ipsum dolor sit amet.
  2. Lorem ipsum dolor sit amet.
  3. Lorem ipsum dolor sit amet.

Y con esto has descubierto la otra pseudo-clase que quería enseñarte hoy:

  • x:first-of-type permite seleccionar, de entre todos los hijos directos de un nodo, el primero de tipo x
  • x:last-of-type hace lo propio con el último de ese tipo
  • x:nth-of-type(i) permite seleccionar i-ésimo hijo de un elemento cuyo tipo sea x (por ejemplo, strong:nth-of-type(2) sería la segunda etiqueta strong que sea hija directa de un elemento)

Seleccionando lo opuesto con :not

Finalmente, la pseudo-clase de la que te quería hablar hoy es :not. :not es una pseudo-clase que permite seleccionar aquellos elementos que no cumplen una cierta propiedad. Por ejemplo, volvamos al ejemplo de la lista cuyos elementos estaban separados por barras azules:

  • Uno
  • Dos
  • Tres

Para solucionar el problema de la barra que aparece en el último elemento, lo que hemos hecho en la sección anterior ha sido (1) añadir la barra a todos los elementos li de mi lista y (2) ocultar la barra en el último:

ul li {
  display: inline;
}

  ul li::after {
    color: #21acde;
    content: " | ";
    display: inline-block;
  }

    ul li:last-child::after {
      display: none;
    }

Esto no parece muy óptimo, ¿no crees? Aquí estamos aplicando unos estilos a todos los elementos li y luego, en el último li, deshacemos lo que acabamos de hacer. Parece complicado y rebuscado. Lo que en realidad queríamos era «añadir la barra a todos los elementos, salvo el último» y ya…

Pues esto lo podemos conseguir aplicando la pseudo-clase :not: y combinándola con :last-child:

ul li {
  display: inline;
}

  ul li:not(:last-child)::after {
    color: #21acde;
    content: " | ";
    display: inline-block;
  }

la cual aplica el estilo a todos los li que no sean el último elemento (:not(:last-child)) y nos da exactamente el resultado esperado:

  • Uno
  • Dos
  • Tres

Resumiendo

Los pseudo-elementos y las pseudo-clases de CSS nos permiten ser mucho más finos a la hora de acceder a los diferentes elementos de nuestra web. Con ellos, podemos escribir CSS más concisos y específicos, lo cual simplifica el mantenimiento de los mismos y evita las posibilidades de tener que estar sobrescribiendo continuamente reglas genéricas para casos concretos (ya que evitamos crear reglas genéricas en primera instancia).

¡Espero que te haya gustado la entrada de hoy y, si es así, compártela con tus amigos y conocidos!

Imagen destacada de JFL en Unsplash.

Deja una respuesta

No publicaremos tu correo electrónico. Los campos obligatorios están marcados con: •

He leído y acepto la Política de privacidad de Nelio Software

Al marcar la casilla de aceptación estás dando tu legítimo consentimiento para que tu información personal se almacene en SiteGround y sea usada por Nelio Software con el propósito único de publicar aquí este comentario. Contáctanos para corregir, limitar, eliminar o acceder a tu información.