Selectores y especificidad
💡 🎯 Al terminar esta lección podrás…
- Elegir elementos con combinadores y selectores de atributo.
- Aplicar estilos según estados y posiciones con pseudoclases.
- Crear decoraciones con pseudoelementos.
- Calcular la especificidad y escribir CSS fácil de mantener.
1.Selectores básicos
| Selector | Elige… | Ejemplo |
|---|---|---|
| Universal | Todos los elementos | * { … } |
| Elemento | Todas las etiquetas de ese tipo | p { … } |
| Clase | Elementos con class="aviso" | .aviso { … } |
| Identificador | El elemento con id="portada" | #portada { … } |
| Agrupación | Varios selectores con una sola regla | h1, h2, h3 { … } |
| Elemento + clase | Solo los p con esa clase | p.aviso { … } |
| Varias clases | Elementos con ambas clases | .boton.grande { … } |
💡 Consejo · Clases, no ids
Los id deben ser únicos y tienen mucha especificidad, lo que dificulta sobrescribirlos. Para dar estilo, usa clases. Reserva los id para enlaces ancla y para JavaScript.
2.Combinadores: relaciones entre elementos
Los combinadores te permiten elegir un elemento por su posición respecto a otros:
| Combinador | Significa | Ejemplo | Elige… |
|---|---|---|---|
| (espacio) | Descendiente (cualquier nivel) | nav a | Todos los a dentro de un nav |
> | Hijo directo | ul > li | Solo los li que son hijos directos del ul |
+ | Hermano inmediato | h2 + p | El p justo después de un h2 |
~ | Cualquier hermano posterior | h2 ~ p | Todos los p posteriores al h2 (mismo padre) |
Observa que el párrafo 3 es negrita pero no azul: es descendiente, pero no hijo directo.
3.Selectores de atributo
Eligen elementos según sus atributos. Son perfectos para formularios y enlaces, y evitan tener que inventar clases:
| Selector | Elige… |
|---|---|
[disabled] | Elementos que tienen el atributo |
[type="email"] | Atributo con ese valor exacto |
[href^="https"] | El valor empieza con… |
[href$=".pdf"] | El valor termina con… |
[href*="ejemplo"] | El valor contiene… |
[class~="a"] | Una palabra de la lista de clases |
4.Pseudoclases: estados y posiciones
Una pseudoclase (con un solo :) elige un elemento en cierto estado o posición, sin necesitar una clase en el HTML:
| Pseudoclase | Cuándo se aplica |
|---|---|
:hover | El cursor está encima |
:focus / :focus-visible | El elemento tiene el foco (:focus-visible solo con teclado) |
:active | Mientras se pulsa |
:visited / :link | Enlace visitado / no visitado |
:checked, :disabled, :required | Estados de los campos de formulario |
:valid / :invalid | El campo cumple (o no) su validación |
:first-child, :last-child | Primer / último hijo de su padre |
:nth-child(n) | Por posición: 2, odd, even, 3n, n+2 |
:not(selector) | Todo lo que no coincide con el selector |
:is(a, b) y :where(a, b) | Agrupa selectores sin repetir (:where no añade especificidad) |
:has(selector) | El elemento que contiene algo (el «selector padre») |
📌 Nota · :has()
:has() es relativamente nuevo, pero ya funciona en todos los navegadores modernos. Permite cosas que antes necesitaban JavaScript, como estilizar una tarjeta según lo que contiene.
5.Pseudoelementos
Un pseudoelemento (con ::) elige una parte de un elemento o crea una decorativa:
| Pseudoelemento | Elige… |
|---|---|
::before / ::after | Contenido generado antes / después (requiere content) |
::first-line | La primera línea de un texto |
::first-letter | La primera letra (capitulares) |
::marker | La viñeta o el número de una lista |
::placeholder | El texto de ayuda de un campo |
::selection | El texto seleccionado por la persona |
⚠️ Importante · content y accesibilidad
El texto generado con content no siempre lo leen los lectores de pantalla y no se puede seleccionar. Úsalo solo para decoración, nunca para información importante.
6.Especificidad: cómo se calcula
Cuando dos reglas apuntan al mismo elemento, gana la de mayor especificidad. Se calcula como tres números, de más a menos importante:
| Columna | Cuenta… | Ejemplos |
|---|---|---|
| A | Identificadores (#id) | #portada → 1,0,0 |
| B | Clases, atributos y pseudoclases | .aviso, [type], :hover → 0,1,0 |
| C | Elementos y pseudoelementos | p, ::before → 0,0,1 |
| Selector | Especificidad |
|---|---|
p | 0,0,1 |
.aviso | 0,1,0 |
p.aviso | 0,1,1 |
nav ul li a | 0,0,4 |
.menu .item:hover | 0,3,0 |
#portada | 1,0,0 |
#portada .titulo | 1,1,0 |
Se comparan columna a columna de izquierda a derecha, no se suman como un número. Así, un solo id (1,0,0) gana a cien clases (0,100,0).
- El estilo en línea (
style="…") supera a todo lo anterior. !importantsupera incluso al estilo en línea.*y los combinadores no suman nada.:where()siempre vale 0;:is()y:not()toman el valor de su argumento más específico.
Calcula la especificidad de cada regla en papel antes de mirar el resultado. Después quita el !important y vuelve a predecir.
7.Estrategia para mantener la especificidad baja
- Usa clases casi siempre; evita
idy!importanten estilos. - Evita selectores largos como
div.contenedor ul li a.enlace: cuanto más largos, más difíciles de sobrescribir. - Ordena de general a específico: elementos primero, componentes después, variantes al final.
- Nombra por función, no por apariencia:
.aviso, no.caja-amarilla. - Usa una convención como BEM (Bloque__Elemento--Modificador):
.tarjeta,.tarjeta__titulo,.tarjeta--destacada.
.tarjeta { padding: 1rem; border: 1px solid #ddd; }
.tarjeta__titulo { font-size: 1.2rem; }
.tarjeta--destacada { border-color: #4f46e5; }
Con BEM cada selector tiene una sola clase (especificidad 0,1,0), así que el orden manda y nunca hay sorpresas.
8.Errores frecuentes
- Confundir
:con::::hoveres una pseudoclase;::beforees un pseudoelemento. - Dejar un espacio donde no va:
p .aviso(descendiente) no es lo mismo quep.aviso(elpcon esa clase). - Olvidar
contenten::beforey::after: sin él no aparece nada. - Creer que
h2 ~ pelige todos los párrafos: solo los hermanos posteriores con el mismo padre. - Sumar especificidades como números: 0,1,10 no es 20.
- Subir la especificidad para ganar en lugar de reorganizar el CSS.
📒 Apuntes para llevar
- Elementos, clases (
.), ids (#), universal (*) y agrupación con comas son la base. - Combinadores: espacio (descendiente),
>(hijo),+(hermano inmediato),~(hermanos posteriores). - Los selectores de atributo (
[type="email"],[href^="https"]) estilizan sin añadir clases. - Las pseudoclases (
:hover,:focus-visible,:nth-child(),:not(),:has()) eligen por estado o posición. - Los pseudoelementos (
::before,::after,::first-letter,::marker) eligen partes o crean decoración;::beforey::afternecesitancontent. - Especificidad = (ids, clases/atributos/pseudoclases, elementos), comparada de izquierda a derecha.
- Mantén la especificidad baja: clases, nombres por función y BEM.
- Usa
!importantsolo como último recurso.
9.Glosario
| Término | Significado |
|---|---|
| Combinador | Símbolo que relaciona dos selectores (espacio, >, +, ~). |
| Pseudoclase | Estado o posición de un elemento (:hover, :first-child). |
| Pseudoelemento | Parte de un elemento o contenido generado (::before). |
| Especificidad | Peso de un selector para decidir qué regla gana. |
| BEM | Convención de nombres: Bloque__Elemento--Modificador. |
:has() | Pseudoclase que elige un elemento según lo que contiene. |
content | Propiedad que define el texto o imagen de ::before y ::after. |
| Selector de atributo | Selector que elige por atributos y sus valores. |
🧠 Comprueba lo aprendido
Elige una respuesta en cada pregunta. Verás al instante si acertaste y por qué.
¿Qué elige ul > li?
> es el combinador de hijo directo: no incluye nietos.
¿Cuál tiene mayor especificidad?
Un id (1,0,0) supera a cualquier cantidad de clases (0,3,0) o elementos (0,0,3).
Escribes .caja::before { color: red; } y no aparece nada. ¿Qué falta?
::before y ::after solo existen si tienen content, aunque sea "".
¿Qué elige a[href$=".pdf"]?
$= significa «termina con»; ^= «empieza con» y *= «contiene».
¿Cuál es la especificidad de #menu .item:hover?
Un id (1), una clase y una pseudoclase (2 en la columna B) y ningún elemento (0): 1,2,0.
Tu progreso se guarda en este navegador y se refleja en el índice del curso.
💡 🚀 ¡Ahora te toca!
La práctica fija lo aprendido. Pasa al ejercicio de esta lección.