
Estilos CSS: Selectores, combinadores y pseudo-clases
- Dacadev
- Programación
- June 4, 2026
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. Especificidad0,0,1. - Selector de clase (
.media) — apunta a los elementos con esa clase. Especificidad0,1,0. - Selector de ID (
#sidebar) — apunta al elemento con eseid. Especificidad1,0,0. - Selector universal (
*) — apunta a todos los elementos. Especificidad0,0,0.
Combinadores
Los combinadores unen selectores simples para describir una relación entre elementos.
| Combinador | Símbolo | Significado | Ejemplo |
|---|---|---|---|
| Descendiente | (espacio) | Cualquier descendiente | .menu li |
| Hijo directo | > | Hijo inmediato | .lista > li |
| Hermano adyacente | + | El elemento inmediatamente siguiente | p + h2 |
| Hermano general | ~ | Todos los hermanos posteriores | li.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 propiedadcontent.::after— inserta un último hijo virtual. Requierecontent.::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).
| Selector | Coincide cuando el atributo… | Ejemplo |
|---|---|---|
[attr] | existe | input[disabled] |
[attr="valor"] | es exactamente igual | input[type="radio"] |
[attr^="valor"] | empieza con el valor | a[href^="https"] |
[attr$="valor"] | termina con el valor | a[href$=".pdf"] |
[attr*="valor"] | contiene el valor | [class*="sprite-"] |
[attr~="valor"] | es una lista separada por espacios que incluye el valor | a[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.


