Especificidad

El podcast de CSS 003: Especificidad

Supongamos que trabajas con los siguientes elementos HTML y CSS:

<button class="branding">Hello, Specificity!</button>
button {
  color: red;
}

.branding {
  color: blue;
}

Aquí hay dos reglas que compiten entre sí. Uno le coloreará el botón de rojo y el otro, de color azul. ¿Qué regla se aplica al elemento? Comprender el algoritmo de la especificación de CSS en lo que respecta a la especificidad es la clave para comprender cómo CSS decide entre reglas competidoras.

La especificidad es una de las cuatro etapas distintas de la cascada, que se abordó en el último módulo sobre la cascada.

Puntuación de especificidad

Cada regla del selector obtiene una puntuación. Puedes pensar en la especificidad como una puntuación total, y cada tipo de selector gana puntos para alcanzarla. El selector con la puntuación más alta gana.

Con la especificidad en un proyecto real, el equilibrio es asegurarse de que las reglas de CSS que esperas aplicar realmente se apliquen, a la vez que, por lo general, se mantienen las puntuaciones bajas para evitar la complejidad. La puntuación solo debe ser tan alta como sea necesario, en lugar de aspirar a la puntuación más alta posible. En el futuro, es posible que se deban aplicar algunos CSS realmente más importantes. Si obtienes la puntuación más alta, harás que ese trabajo sea difícil.

Puntuación de cada tipo de selector

Cada tipo de selector gana puntos. Agrega todos estos puntos para calcular la especificidad general de un selector.

Selector universal

Un selector universal (*) no tiene especificidad y obtiene 0 puntos. Esto significa que cualquier regla que tenga 1 o más puntos la anulará.

* {
  color: red;
}

Selector de elemento o seudoelemento

Un selector de elemento (tipo) o pseudoelemento obtiene 1 punto de especificidad .

Selector de tipos

div {
  color: red;
}

Selector de seudoelementos

::selection {
  color: red;
}

Selector de clase, pseudoclase o atributo

Un selector de clase, pseudoclase o atributo obtiene 10 puntos de especificidad.

Selector de clases

.my-class {
  color: red;
}

Selector de pseudoclase

:hover {
  color: red;
}

Selector de atributos

[href='#'] {
  color: red;
}

La seudoclase :not() en sí misma no agrega nada al cálculo de especificidad. Sin embargo, los selectores pasados como argumentos se agregan al cálculo de especificidad.

div:not(.my-class) {
  color: red;
}

Este ejemplo tendría 11 puntos de especificidad porque tiene un selector de tipos (div) y una clase dentro de :not().

Selector de ID

Un selector de ID obtiene 100 puntos de especificidad, siempre que uses un selector de ID (#myID) y no un selector de atributos ([id="myID"]).

#myID {
  color: red;
}

Atributo de estilo intercalado

El CSS que se aplica directamente al atributo style del elemento HTML obtiene una puntuación de especificidad de 1,000 puntos. Esto significa que, para anularlo en CSS, debes escribir un selector extremadamente específico.

<div style="color: red"></div>

Regla !important

Por último, un elemento !important al final de un valor de CSS obtiene una puntuación de especificidad de 10,000 puntos. Esta es la especificidad más alta que puede obtener un elemento individual.

Se aplica una regla !important a una propiedad de CSS, por lo que no todos los elementos de la regla general (selector y propiedades) obtienen la misma puntuación de especificidad.

.my-class {
  color: red !important; /* 10,000 points */
  background: white; /* 10 points */
}

Verifica tus conocimientos

Pon a prueba tus conocimientos sobre la puntuación de especificidad

¿Cuál es la puntuación de especificidad de a[href="#"]?

1
La a vale 1 punto, pero la [href="#"] vale 10.
5
Vuelve a intentarlo.
11
La a vale 1 punto y la [href="#"] equivalen a 10 puntos, lo que hace un total de 11 puntos.

Especificidad en contexto

La especificidad de cada selector que coincide con un elemento se suma en conjunto. Considera este código HTML de ejemplo:

<a class="my-class another-class" href="#">A link</a>

Este vínculo tiene dos clases. Agrega el siguiente CSS y obtiene 1 punto de especificidad:

a {
  color: red;
}

Haz referencia a una de las clases de esta regla, que ahora tiene 11 puntos de especificidad:

a.my-class {
  color: green;
}

Agrega la otra clase al selector; ahora tiene 21 puntos de especificidad:

a.my-class.another-class {
  color: rebeccapurple;
}

Agrega el atributo href al selector. Ahora tiene 31 puntos de especificidad:

a.my-class.another-class[href] {
  color: goldenrod;
}

Por último, agrega una seudoclase :hover a todo eso; el selector terminará con 41 puntos de especificidad:

a.my-class.another-class[href]:hover {
  color: lightgrey;
}

Verifica tus conocimientos

Pon a prueba tus conocimientos sobre la puntuación de especificidad

¿Cuál de los siguientes selectores vale 21 puntos?

article > section
Los elementos valen 1 punto. Hay 2 elementos en el selector, por lo que valen 2 puntos.
article.card.dark
Los elementos valen 1 punto, las clases 10 puntos y, con 2 clases y 1 elemento, lo que hace que el selector valga 21 puntos.
article:hover a[href]
Los elementos valen 1 punto, las seudoclases y los atributos valen 10 puntos, hay 2 puntos por los elementos y 20 puntos para los atributos y las clases, por lo que este selector vale 22 puntos.

Visualización de la especificidad

En los diagramas y las calculadoras de especificidad, la especificidad a menudo se visualiza de la siguiente manera:

Un diagrama que muestra los selectores más específicos a los menos específicos

El grupo izquierdo es id selectores. El segundo grupo son los selectores de clase, atributo y seudoclase. El grupo final son los selectores de elementos y pseudoelementos.

Como referencia, el siguiente selector es 0-4-1:

a.my-class.another-class[href]:hover {
  color: lightgrey;
}

Verifica tus conocimientos

Pon a prueba tus conocimientos sobre la visualización de especificidad

¿Cuál de los siguientes selectores es 1-2-1?

section#specialty.dark
Este selector se visualiza como 1-1-1.
#specialty:hover li.dark
🎉
[data-state-rad].dark#specialty:hover
Este selector se visualiza como 1-3-0.
li#specialty section.dark
Este selector se visualiza como 1-1-2.

Especificidad que aumenta de manera pragmáticamente

Supongamos que tenemos algunas CSS que se ven de la siguiente manera:

.my-button {
  background: blue;
}

button[onclick] {
  background: grey;
}

Con HTML que se ve de la siguiente manera:

<button class="my-button" onclick="alert('hello')">Click me</button>

El botón tiene un fondo gris porque el segundo selector obtiene 11 puntos de especificidad (0-1-1). Esto se debe a que tiene un selector de tipo (button), que es de 1 punto y un selector de atributos ([onclick]), que es de 10 puntos.

La regla anterior, .my-button, obtiene 10 puntos (0-1-0), porque tiene un selector de clases.

Si quieres potenciar esta regla, repite el selector de clases de la siguiente manera:

.my-button.my-button {
  background: blue;
}

button[onclick] {
  background: grey;
}

Ahora, el botón tendrá un fondo azul, ya que el nuevo selector obtiene una puntuación de especificidad de 20 puntos (0-2-0).

Una puntuación de especificidad coincidente registra la victoria de la instancia más reciente

Por ahora, usemos el ejemplo del botón y cambiemos la CSS a lo siguiente:

.my-button {
  background: blue;
}

[onclick] {
  background: grey;
}

El botón tiene un fondo gris, porque ambos selectores tienen una puntuación de especificidad idéntica (0-1-0).

Si cambias las reglas en el orden de origen, el botón será azul.

[onclick] {
  background: grey;
}

.my-button {
  background: blue;
}

Esta es la única instancia en la que gana el CSS más nuevo. Para hacerlo, debe coincidir con la especificidad de otro selector que se oriente al mismo elemento.

Recursos