Especificidad CSS

La especificidad en selectores CSS


Curiosamente, la Especificidad CSS es uno de los detalles más importantes de CSS, y a la misma vez es de las cosas que, sorprendemente, mucha gente desconoce, aún cuando debería ser esencial conocerlo.

La Especificidad CSS es el nombre que recibe un mecanismo del navegador que se encarga de, en el caso de que exista ambigüedad y hayan varios bloques de estilos compitiendo uno contra otro para dar estilo a un mismo elemento, resolver dicha ambigüedad y decidir cuál es el grupo de estilos «vencedor».

Para ello, el navegador analiza los selectores y le otorga un valor numérico. El selector que tenga el valor numérico más alto, es el que finalmente aplicará sus estilos.

Los desarrolladores suelen pensar que CSS funciona similar a un lenguaje de programación como Javascript, y que simplemente los estilos vencedores son los que se escriben más abajo en el CSS. Y cuando esto no funciona, usan un !important. Por eso se debe conocer la Especificidad CSS.

Conflictos de especificidad CSS

Para entenderlo, vamos a ver un ejemplo donde habría un conflicto de especificidad CSS. Observa el siguiente fragmento de código e imaginemos lo que haría el navegador. Recalcar que el mismo elemento HTML tiene tanto id como clase:

#element {
  background: indigo;
  color: white;
}

.container {
  background: red;
}
<div id="element" class="container">Hola, mi página es Manz.dev</div>

En este caso, tenemos un conflicto, ya que existe ambigüedad. Ambos bloques están seleccionando el mismo elemento y están compitiendo para la propiedad CSS background. Como se puede ver en la demo, el vencedor es el selector #element. Sin embargo, muchas personas piensan que, como se seleccionan ambos, vence el que está más abajo porque sobreescribe el anterior. Esto es erróneo.

¿Cómo se calcula la Especificidad?

El navegador tiene un sistema llamado Especificidad CSS, donde en situaciones de conflicto como la anterior, calculará que selector es más específico, siguiendo unas ciertas normas, y obtienendo como resultado un valor numérico.

Dicho valor numérico se suele representar con 3 cifras, separadas por comas: A,B,C:

ValorDescripción
Valor ANúmero de veces que aparece un #id en el selector.
Valor BNúmero de veces que aparece una .clase, [atributo] o :pseudoclase en el selector.
Valor CNúmero de veces que aparece un elemento o un ::pseudoelemento en el selector.

Teniendo en cuenta esto, veamos algunos ejemplos con diferentes selectores CSS y calculemos su cifra de especificidad CSS. Recuerda que cuanto más alta sea, más específico es el selector.

Al final, el selector con especificidad más alta es el que gana los selectores en conflicto que compite:

div { ... }                   /* 0,0,1 (1 elemento HTML) */
div div { ... }               /* 0,0,2 (2 elementos HTML) */
#pagina div { ... }           /* 1,0,1 (1 id y 1 elemento HTML) */
#pagina div:hover { ... }     /* 1,1,1 (1 id, 1 pseudoclase y 1 elemento HTML) */
#pagina div:hover a { ... }   /* 1,1,2 (1 id, 1 pseudoclase y 2 elementos HTML) */
#pagina .sel:hover>a { ... }  /* 1,2,1 (1 id, 1 clase, 1 pseudoclase y 1 elemento HTML) */

Estos cálculos no hace falta hacerlos a mano o mentalmente, existen calculadoras de especificidad que pueden darte el valor por si tienes curiosidad por saber cuál tiene mayor o menor especificidad. De hecho, las DevTools del navegador, también suelen mostrar la especificidad si mueves el ratón sobre el selector.

Formas alternativas de ver la especificidad de un selector CSS:

Existen excepciones en la forma de calcular la especificidad CSS, como por ejemplo en los combinadores :is() o :where(), que explicaremos más adelante.

Excepciones de Especificidad CSS

Recuerda que también hay ciertas excepciones a la hora de calcular la especificidad CSS (puedes comprobarlo también en las calculadoras de especificidad anteriores):

ExcepciónCómo se modifica la especificidad de su interior
1️⃣ Combinador :is()Se suma la especificidad del selector más específico de la lista.
2️⃣ Combinador :not()Usa la misma especificidad del selector que contiene.
3️⃣ Combinador :has()Usa la especificidad base (10) más la del selector que contiene.
4️⃣ Combinador :where()No importa el selector interno. Su especificidad siempre es 0.

Veamos un fragmento de código para afianzar los conceptos de estos combinadores CSS :is(), :not(), :has() y :where() con los siguientes ejemplos:

.container { }                       /* Especificidad: 0,1,0 */
.container .item { }                 /* Especificidad: 0,2,0 */

.container :is(.item, #unique) { }   /* 1,1,0 (#unique es el más específico) */
.container :not(.item) { }           /* 0,2,0 */
.container:has(.item) { }            /* 0,2,0 */
.container :where(.item) { }         /* 0,1,0 (solo cuenta el de fuera) */

¿Quién soy yo?

Soy Manz, vivo en Tenerife (España) y soy streamer partner en Twitch y profesor. Me apasiona el universo de la programación web, el diseño y desarrollo web y la tecnología en general. Aunque soy full-stack, mi pasión es el front-end, la terminal y crear cosas divertidas y locas.

Puedes encontrar más sobre mi en Manz.dev