Estilos CSS: Selectores, combinadores y pseudo-clases

Estilos CSS: Selectores, combinadores y pseudo-clases

Table of Contents

Un selector es el mecanismo con el que CSS apunta a los elementos que vas a estilizar. Elegir el selector correcto no es solo cuestión de que “funcione”: impacta directamente en la especificidad, en el acoplamiento de tus estilos y en la facilidad para mantenerlos. CSS ofrece un catálogo amplio de selectores, y conocerlos a fondo te evita escribir reglas frágiles.

Este artículo es la segunda entrega de la serie Estilos CSS. Recorreremos los selectores básicos, los combinadores, las pseudo-clases, los pseudo-elementos y los selectores de atributo, con ejemplos que puedes ver renderizados aquí mismo.

Note

Repasaremos cada familia de selectores con su especificidad y demostraciones en vivo, para que puedas elegir siempre la opción más precisa y de menor acoplamiento.

Selectores básicos

Son los cuatro selectores fundamentales sobre los que se construye todo lo demás:

  • Selector de tipo (p, h1) — apunta por nombre de etiqueta. Especificidad 0,0,1.
  • Selector de clase (.media) — apunta a los elementos con esa clase. Especificidad 0,1,0.
  • Selector de ID (#sidebar) — apunta al elemento con ese id. Especificidad 1,0,0.
  • Selector universal (*) — apunta a todos los elementos. Especificidad 0,0,0.

Combinadores

Los combinadores unen selectores simples para describir una relación entre elementos.

CombinadorSímboloSignificadoEjemplo
Descendiente(espacio)Cualquier descendiente.menu li
Hijo directo>Hijo inmediato.lista > li
Hermano adyacente+El elemento inmediatamente siguientep + h2
Hermano general~Todos los hermanos posterioresli.activo ~ li

El combinador de hijo directo (>) solo afecta al primer nivel de descendientes. Observa la diferencia con el descendiente:

.lista > li { font-weight: bold; }   /* solo hijos directos */
<ul class="lista">
  <li>Hijo directo (en negrita)</li>
  <li>Hijo directo (en negrita)
    <ul>
      <li>Nieto (sin negrita)</li>
    </ul>
  </li>
</ul>
  • Hijo directo (en negrita)
  • Hijo directo (en negrita)
    • Nieto (sin negrita)

Selectores compuestos

Varios selectores simples se pueden unir sin espacios para formar un selector compuesto que exige que el elemento cumpla todas las condiciones. Por ejemplo, .dropdown.is-active apunta a <div class="dropdown is-active"> pero no a <div class="dropdown">.

Pseudo-clases

Las pseudo-clases apuntan a elementos según un estado: interacción del usuario o posición respecto a sus hermanos. Empiezan con un solo dos puntos (:) y tienen la especificidad de una clase (0,1,0).

Posición estructural

  • :first-child, :last-child, :only-child — primero, último o único hijo.
  • :nth-child(an + b) — apunta según una fórmula posicional entre sus hermanos.
  • :nth-last-child() — igual, pero contando desde el final.
  • :first-of-type, :last-of-type, :nth-of-type() — equivalentes, pero solo cuentan elementos del mismo tipo.
  • :not(<selector>) — apunta a lo que no coincide con el selector interno.
  • :empty — elementos sin hijos.

Un patrón clásico: aplicar un fondo alterno con :nth-child(even) para crear filas tipo “cebra”.

.zebra li:nth-child(even) { background: #ecf0f1; }
  • Fila 1
  • Fila 2 (resaltada)
  • Fila 3
  • Fila 4 (resaltada)

Estado e interacción

  • :hover — mientras el cursor está sobre el elemento.
  • :focus — cuando el elemento recibe foco (clic, toque o tabulación).
  • :root — el elemento raíz del documento.

Campos de formulario

Varias pseudo-clases describen el estado de los controles: :disabled, :enabled, :checked, :invalid, :valid, :required, :optional. Aquí, :invalid cambia el borde cuando el valor no es un correo válido:

input:invalid { border-color: #c0392b; }
input:valid   { border-color: #27ae60; }

Tip

La lista de pseudo-clases es extensa y evoluciona con cada nivel de la especificación. Consulta la documentación de MDN sobre pseudo-clases para el catálogo completo y el soporte por navegador.

Pseudo-elementos

Los pseudo-elementos no apuntan a un elemento existente, sino a una parte del documento que no tiene marcado propio, o inyectan contenido nuevo. Usan doble dos puntos (::) y tienen la especificidad de un selector de tipo (0,0,1).

  • ::before — inserta un primer hijo virtual. Requiere la propiedad content.
  • ::after — inserta un último hijo virtual. Requiere content.
  • ::first-letter — estiliza la primera letra del texto.
  • ::first-line — estiliza la primera línea.
  • ::selection — estiliza el texto que el usuario resalta.
.nota::before { content: "★ "; color: #f39c12; }
.capitular::first-letter { font-size: 2.5em; font-weight: bold; color: #2a9da9; }

Texto precedido por un pseudo-elemento ::before.

Lorem ipsum con la primera letra estilizada como capitular.

Selectores de atributo

Apuntan a elementos según sus atributos HTML. Tienen la especificidad de una clase (0,1,0).

SelectorCoincide cuando el atributo…Ejemplo
[attr]existeinput[disabled]
[attr="valor"]es exactamente igualinput[type="radio"]
[attr^="valor"]empieza con el valora[href^="https"]
[attr$="valor"]termina con el valora[href$=".pdf"]
[attr*="valor"]contiene el valor[class*="sprite-"]
[attr~="valor"]es una lista separada por espacios que incluye el valora[rel~="author"]
[attr|="valor"]es igual o empieza con valor-[lang|="es"]

Por ejemplo, podemos marcar visualmente los enlaces externos y los que apuntan a un PDF:

a[href^="https"]::after { content: " ↗"; }
a[href$=".pdf"]::after  { content: " (PDF)"; color: #c0392b; }

Info

Los selectores de atributo distinguen mayúsculas y minúsculas por defecto. La especificación nivel 4 añade un modificador i antes del corchete de cierre —input[value="search" i]— para hacerlos insensibles a mayúsculas. Verifica el soporte antes de usarlo en producción.

Conclusión

El catálogo de selectores de CSS es amplio y cada familia resuelve un problema distinto. La clave está en elegir el selector más preciso con la menor especificidad posible: eso mantiene tus estilos desacoplados y fáciles de sobrescribir cuando lo necesites.

Note

🚀 En la siguiente entrega abordamos el modelo de caja: cómo margin, border, padding y content definen el tamaño real de cada elemento y cómo box-sizing cambia las reglas del juego.

Tags :