En esta página

Especificidad: como CSS decide que estilo gana

10 min lectura TextoCap. 1 — Base de CSS

Cómo decide CSS que estilo aplicar?

Cuando multiples reglas CSS apuntan al mismo elemento, el navegador necesita un sistema para decidir cual gana. Ese sistema se llama la cascada y se basa en tres factores, evaluados en este orden:

  1. Origen e importancia (estilos del usuario, del autor, del navegador)
  2. Especificidad del selector
  3. Orden de aparicion en el código

Qué es la especificidad?

La especificidad es un valor numérico que el navegador asigna a cada selector CSS. Se representa como una tupla de tres números: (ID, Clase, Elemento).

Selector ID Clase Elemento Valor
p 0 0 1 (0,0,1)
.card 0 1 0 (0,1,0)
p.card 0 1 1 (0,1,1)
#hero 1 0 0 (1,0,0)
#hero .card p 1 1 1 (1,1,1)

Cada columna se compara de izquierda a derecha. Un solo ID (1,0,0) supera a cien clases (0,100,0) porque la columna de ID se evalua primero.

Que cuenta como "clase"?

En la columna de clase se suman:

  • Selectores de clase (.card)
  • Selectores de atributo ([type="text"])
  • Pseudo-clases (:hover, :focus, :nth-child())

Que cuenta como "elemento"?

En la columna de elemento se suman:

  • Selectores de tipo (div, p, h1)
  • Pseudo-elementos (::before, ::after, ::placeholder)

El selector universal y los combinadores

El selector universal (*), los combinadores (>, +, ~, ) y la pseudo-clase :where() tienen especificidad cero. No suman nada.

/* Ambos tienen especificidad (0, 1, 0) */
.card { color: red; }
*.card { color: blue; } /* Misma especificidad */

La pseudo-clase :is() y :not()

A diferencia de :where(), las pseudo-clases :is() y :not() toman la especificidad del argumento más específico que contienen.

/* Especificidad: (1, 0, 0) por el #hero dentro de :is() */
:is(#hero, .card, p) {
  color: red;
}

La cascada: orden de aparicion

Cuando dos selectores tienen la misma especificidad, gana el que aparece último en el código fuente.

.título { color: blue; }
.título { color: red; }  /* Gana: aparece despues */

Capas de cascada con @layer

CSS moderno introduce @layer para controlar la prioridad sin depender del orden fisico del código. Las capas declaradas despues tienen mayor prioridad.

@layer base, componentes, utilidades;

@layer base {
  .boton { padding: 0.5rem; }
}

@layer utilidades {
  .boton { padding: 1rem; } /* Gana por ser capa posterior */
}

Estilos inline y !important

Los estilos inline (style="...") superan cualquier selector en la hoja de estilos. Solo !important puede superarlos, pero su uso excesivo dificulta el mantenimiento.

La prioridad completa, de menor a mayor, es:

  1. Estilos del navegador (user-agent)
  2. Estilos del autor (tus CSS)
  3. Estilos del autor con !important
  4. Estilos inline
  5. Estilos inline con !important

Estrategia recomendada

Para mantener CSS predecible:

  • Usa clases como base de tus selectores
  • Evita IDs para estilos (reservalos para JavaScript o anclas)
  • Evita !important salvo para utilidades muy especificas
  • Usa @layer para organizar la prioridad entre base, componentes y utilidades
  • Mantiene selectores simples: un nivel de clase suele ser suficiente

Ahora que entiendes como CSS resuelve conflictos, en la siguiente leccion exploraremos el box model, la base de todo el layout en CSS.

Práctica

  1. Calcula la especificidad: Escribe cinco selectores distintos que apunten al mismo elemento y ordenalos de menor a mayor especificidad. Verifica tu calculo abriendo el inspector del navegador.
  2. Organiza con @layer: Crea tres capas (base, componentes, utilidades) con @layer y define reglas conflictivas en cada una. Comprueba que la capa declarada al final tiene mayor prioridad.
  3. Elimina un !important: Busca un caso donde necesites !important y refactoriza los selectores para que el estilo correcto gane solo por especificidad o por orden de cascada.
Recuerda
La especificidad se calcula como (ID, clase, elemento). Un solo selector de ID supera a cualquier cantidad de clases. Evita usar !important: es una señal de que la arquitectura CSS necesita mejoras.
Cuidado con !important
Usar !important rompe el flujo natural de la cascada. Solo usalo como último recurso, por ejemplo para sobreescribir estilos de terceros que no puedes modificar.
/* Especificidad: (0, 0, 1) */
p {
  color: black;
}

/* Especificidad: (0, 1, 0) */
.mensaje {
  color: blue;
}

/* Especificidad: (0, 1, 1) */
p.mensaje {
  color: green;
}

/* Especificidad: (1, 0, 0) */
#alerta {
  color: red;
}

/* Especificidad: (0, 2, 0) - mayor que (0, 1, 1) */
.contenedor .mensaje {
  color: purple;
}
/* Ambos selectores tienen la misma
   especificidad: (0, 1, 0) */

.boton {
  background-color: blue;
  color: white;
}

/* Este gana por orden: esta despues */
.boton {
  background-color: green;
}

/* Usar capas para controlar prioridad */
@layer base, componentes, utilidades;

@layer base {
  .boton { background: gray; }
}

@layer componentes {
  .boton { background: blue; }
}

@layer utilidades {
  .boton { background: green; } /* Gana */
}