ToolPal
CSS code on a computer screen

Especificidad CSS de una vez por todas: por qué tus estilos no se aplican

📷 Negative Space / Pexels

Especificidad CSS de una vez por todas: por qué tus estilos no se aplican

La especificidad CSS confunde incluso a desarrolladores experimentados. Aprende el sistema (A,B,C), los errores más comunes y cómo una calculadora de especificidad puede ahorrarte horas de depuración.

13 de abril de 20265 min de lectura

Todo desarrollador front-end conoce ese momento. Escribes una regla CSS, recargas el navegador, y nada cambia. Abres DevTools y ves tu regla tachada, vencida por algún selector que ni recuerdas haber escrito.

La reacción instintiva: añadir !important.

Funciona, claro. Hasta que no funciona, porque hay otro !important con mayor especificidad. Y entonces añades otro. Y en seis meses tienes una hoja de estilos que parece un concurso de gritos.

La especificidad CSS no es complicada. Tiene reglas claras y consistentes. Solo hay que entenderlas una vez de verdad.

El sistema (A, B, C)

La especificidad CSS no es un número único, sino un triplete (A, B, C). La comparación se hace de izquierda a derecha: si A es mayor, ese selector gana, sin mirar B ni C. Si A es igual, se compara B. Si también empatan, se compara C.

A — Selectores de ID #header, #contenido y cualquier #id suman 1 a A, resultando en (1, 0, 0). Esta columna es la razón por la que las buenas prácticas modernas desaconsejan usar IDs para dar estilos — una vez que aparece, sobreescribirlo sin !important es muy difícil.

B — Clases, atributos y pseudoclases Selectores de clase (.nav), de atributo ([type="text"]) y pseudoclases (:hover, :focus, :nth-child()) incrementan B en 1 cada uno. :not() también cuenta via la especificidad de su argumento.

C — Selectores de tipo y pseudoelementos div, p, span y pseudoelementos como ::before y ::after van a C.

Lo que no cuenta El selector universal *, los combinadores (>, +, ~) y :where() contribuyen cero a la especificidad. :where() es especialmente útil para estilos base que quieres que sean fácilmente sobreescribibles.

Ejemplos comparativos

/* (0, 0, 1) */
p { color: red; }

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

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

/* (1, 0, 0) */
#main { color: orange; }

/* (1, 1, 1) */
#main .contenido p { color: purple; }

Si todas estas reglas apuntan al mismo elemento, (1, 1, 1) gana.

Errores comunes

Selectores más largos tienen mayor especificidad

Esta es la confusión más frecuente. .nav .lista .item a.enlace:hover parece muy específico, pero su valor es (0, 4, 2). Un solo #nav con (1, 0, 0) lo supera sin esfuerzo.

La regla que viene después siempre gana

Esto solo aplica cuando la especificidad es exactamente igual. Si los valores difieren, el orden en el archivo no importa — gana el de mayor especificidad, sin excepción.

:is(), :not() y :where()

:not() hereda la especificidad de su argumento. :not(.oculto) equivale a (0, 1, 0) gracias a .oculto.

:is() toma la especificidad del argumento más específico. :is(#header, .nav, p) resulta en (1, 0, 0) por #header, aunque el elemento que coincida sea solo un .nav. Esto sorprende a bastante gente.

:where() siempre es cero. Envolver estilos base en :where() es un patrón muy utilizado en librerías de componentes modernas, ya que cualquier clase simple puede sobreescribirlos fácilmente.

Escenario real: sobreescribir estilos de una librería

Situación clásica en cualquier proyecto con componentes de terceros:

/* CSS de la librería */
.ui-btn.ui-btn--primary {
  background-color: #0066cc;
}

/* Mi sobreescritura */
.mi-boton {
  background-color: #ff5500;
}

Librería: (0, 2, 0). Mi regla: (0, 1, 0). Mi regla pierde.

Soluciones correctas:

  1. Duplicar la clase: .mi-boton.mi-boton sube a (0, 2, 0) — truco válido y reconocido
  2. Añadir contexto padre: .mi-app .mi-boton también da (0, 2, 0)
  3. !important: solo como último recurso

Si controlas la librería, envolver los estilos base en :where() hace que cualquier sobreescritura sea trivial.

La calculadora de especificidad CSS

En lugar de contar mentalmente, la calculadora de especificidad CSS analiza el selector y muestra la descomposición (A, B, C) al instante.

Cuándo usarla:

  • Al depurar: pega los dos selectores en conflicto y ve de un vistazo cuál debería ganar
  • Al escribir CSS: comprueba la especificidad antes de confirmar que un selector es lo que quieres
  • Para aprender: modificar un selector y observar cómo cambian los números es la forma más directa de interiorizar las reglas

Limitaciones del cálculo

Para selectores cotidianos, el cálculo es preciso. Los casos límite aparecen con expresiones :is() muy anidadas y con selectores Shadow DOM (::slotted(), ::part()). Para esos casos, las DevTools del navegador son la referencia definitiva.

Escribir CSS con especificidad controlada

No usar IDs para estilos Los IDs son útiles como anclas HTML y referencias JavaScript, no como selectores CSS. Una vez que aparece (1, 0, 0) en tu hoja de estilos, sobreescribirlo se vuelve un problema.

Selectores cortos .enlace-nav es mejor que nav ul li a.enlace-nav. Un selector corto tiene menor especificidad y es más resistente a cambios en la estructura HTML.

Convenciones como BEM Con BEM (.bloque__elemento--modificador), casi todos los selectores quedan en (0, 1, 0), lo que hace la especificidad predecible y homogénea en todo el proyecto.

!important solo para clases utilitarias .oculto, .visually-hidden, .u-texto-centro son clases que deben ganar siempre — ahí !important es legítimo. En cualquier otro contexto, es una señal de que algo en la arquitectura CSS merece revisión.

Herramientas relacionadas


La especificidad CSS es uno de esos conocimientos que devuelve rentabilidad constantemente. Cuando las reglas están claras — por qué (1, 0, 0) gana a (0, 100, 0), qué hace :where() al cálculo, cómo :is() puede disparar la especificidad sin querer — dejas de pelear contra el navegador y empiezas a trabajar con él. Usa la calculadora de especificidad CSS para depurar rápido y deja que la lógica detrás de los números guíe tu CSS.

Preguntas Frecuentes

Compartir

XLinkedIn

Publicaciones relacionadas