Más allá de la etiqueta, la clase y el id
Los selectores básicos (p, .aviso, #cabecera) te sacan del apuro, pero se
quedan cortos en cuanto el diseño aprieta: "estila el primer ítem del menú", "solo
el enlace activo", "las filas pares de la tabla". Para eso CSS tiene selectores
mucho más expresivos, capaces de apuntar a un elemento por su posición, su
estado o sus atributos, sin tocar una línea del HTML. Y lo mejor: cada
cambio lo ves al instante en pantalla.
Combinadores: relaciones entre elementos
Un combinador relaciona dos selectores según la posición de los elementos en el árbol del documento.
/* Descendiente (espacio): cualquier <a> dentro de un .nav, a cualquier nivel */
.nav a { color: teal; }
/* Hijo directo (>): solo los <li> hijos inmediatos de .menu */
.menu > li { font-weight: bold; }
/* Hermano adyacente (+): el <p> que va JUSTO después de un <h2> */
h2 + p { margin-top: 0; }
/* Hermano general (~): TODOS los <p> hermanos posteriores a un <h2> */
h2 ~ p { color: #555; }
A BseleccionaBque esté dentro deA(a cualquier profundidad).A > Bexige queBsea hijo directo deA.A + Bselecciona el primer hermanoBinmediatamente después deA.A ~ Bselecciona todos los hermanosBque vengan después deA.
El truco para no confundir > con un espacio: el espacio es "en algún sitio ahí
dentro", el > es "justo el hijo, sin nietos".
Pseudo-clases: seleccionar por estado o posición
Una pseudo-clase (un solo :) apunta a un elemento según un estado dinámico
o su posición entre hermanos.
a:hover { text-decoration: underline; } /* al pasar el ratón */
input:focus { outline: 2px solid royalblue; } /* al tener el foco */
li:first-child { font-weight: bold; } /* el primer hijo */
li:last-child { border-bottom: none; } /* el último hijo */
li:nth-child(2) { background: #eef; } /* el 2.º hijo */
li:nth-child(odd) { background: #f7f7f7; } /* impares: 1, 3, 5... */
p:not(.destacado) { opacity: 0.7; } /* todos menos .destacado */
:nth-child() acepta un número, las palabras odd/even, o una fórmula
an+b (por ejemplo 3n para uno de cada tres). Es tu mejor aliado para esas
tablas con filas alternas sin marcar ni una clase a mano.
Pseudo-elementos: estilar partes generadas
Un pseudo-elemento (doble ::) estiliza una parte concreta del elemento o
genera contenido. ::before y ::after insertan contenido y exigen la
propiedad content.
.precio::before { content: "€ "; color: green; }
.enlace-externo::after { content: " ↗"; }
p::first-line { font-weight: bold; }
Sin content, los pseudo-elementos ::before/::after no se muestran. Es el
olvido número uno: la regla parece correcta, pero en pantalla no aparece nada
porque falta el content. Recuérdalo y te ahorras un buen rato de despiste.
Selectores de atributo
Apuntan a elementos según la presencia o el valor de un atributo HTML.
input[type="text"] { border: 1px solid #ccc; } /* valor exacto */
a[target] { font-weight: bold; } /* tenga el atributo */
a[href^="https"] { color: green; } /* empieza por */
img[src$=".png"] { border: 1px solid #ddd; } /* termina en */
a[href*="ejemplo"] { color: orange; } /* contiene */
Combinando estos selectores apuntas con precisión de francotirador a casi cualquier elemento sin ensuciar el HTML con clases de relleno. Menos clases inventadas, CSS más limpio.