¿Cómo se calculan los puntos en la especificidad de CSS?

Resuelto Sam asked hace 14 años • 7 respuestas

Al investigar la especificidad, me topé con este blog: http://www.htmldog.com/guides/cssadvanced/specificity/

Afirma que la especificidad es un sistema de puntuación para CSS. Nos dice que los elementos valen 1 punto, las clases valen 10 puntos y las identificaciones valen 100 puntos. También va arriba decir que estos puntos se suman y que la cantidad total es la especificidad de ese seleccionador.

Por ejemplo:

cuerpo = 1 punto
cuerpo .wrapper = 11 puntos
cuerpo .wrapper #contenedor = 111 puntos

Entonces, usando estos puntos, espero que el siguiente CSS y HTML den como resultado que el texto sea azul:

#a {
    color: red;
}

.a .b .c .d .e .f .g .h .i .j .k .l .m .n .o {
  color: blue;
}
<div class="a">
  <div class="b">
    <div class="c">
      <div class="d">
        <div class="e">
          <div class="f">
            <div class="g">
              <div class="h">
                <div class="i">
                  <div class="j">
                    <div class="k">
                      <div class="l">
                        <div class="m">
                          <div class="n">
                            <div class="o" id="a">
                              This should be blue.
                            </div>
                          </div>
                        </div>
                      </div>
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>
Expandir fragmento

¿Por qué el texto está en rojo cuando 15 clases equivaldrían a 150 puntos en comparación con 1 identificación que equivale a 100 puntos?

Aparentemente los puntos no sólo se suman; están concatenados. Lea más sobre eso aquí: http://www.stuffandnonsense.co.uk/archives/css_specificity_wars.html

¿Eso significa que las clases en nuestro selector = 0,0,15,0OR 0,1,5,0?

(Mis instintos me dicen que es lo primero, ya que SABEMOS que la especificidad del selector de ID se ve así 0,1,0,0:)

Sam avatar May 11 '10 15:05 Sam
Aceptado

La respuesta de Pekka es prácticamente correcta y probablemente sea la mejor manera de pensar sobre el tema.

Sin embargo, como muchos ya han señalado, la recomendación CSS del W3C establece que "Concatenar los tres números abc (en un sistema numérico con una base grande) da la especificidad". Así que el geek que hay en mí tuvo que descubrir qué tan grande es esta base.

Resulta que la "base muy grande" empleada (al menos por los 4 navegadores más utilizados * ) para implementar este algoritmo estándar es 256 o 2 8 .

Lo que esto significa es que un estilo especificado con 0 identificadores y 256 nombres de clases anulará un estilo especificado con solo 1 identificador. Probé esto con algunos violines:

  • 255 clases no son suficientes para anular 1 id

  • ...pero 256 clases son suficientes para anular 1 id

  • ...y 256 nombres de etiquetas son suficientes para anular 1 nombre de clase

  • ...pero, lamentablemente, 256 identificadores no son suficientes para anular 1 estilo en línea (actualizado el 15/8/2012: tendrás que usar !important)

Entonces, efectivamente, existe un "sistema de puntos", pero no es de base 10. Es de base 256. Así es como funciona:

(2 8 ) 2 o 65536, multiplicado por el número de identificadores en el selector

  • (2 8 ) 1 o 256, multiplicado por el número de nombres de clase en el selector
  • (2 8 ) 0 o 1, multiplicado por el número de nombres de etiquetas en el selector

Esto no es muy práctico para ejercicios sencillos para comunicar el concepto.
Probablemente esa sea la razón por la que los artículos sobre el tema han utilizado la base 10.

***** [Opera usa 2 16 (ver el comentario de karlcow). Algunos otros motores de selección usan infinito ; efectivamente, no hay sistema de puntos (consulte el comentario de Simon Sapin).]

Actualización, julio de 2014:
Como señaló Blazemonger a principios de año, los navegadores webkit (Chrome, Safari) ahora parecen utilizar una base superior a 256. ¿Quizás 2 16 , como Opera? IE y Firefox todavía usan 256.

Actualización, marzo de 2021:
Firefox ya no usa 256 como base.

Faust avatar Aug 13 '2012 12:08 Faust

Buena pregunta.

No puedo estar seguro (todos los artículos que logro encontrar evitan el ejemplo de clases múltiples, por ejemplo aquí ), pero supongo que cuando se trata de comparar la especificidad entre un selector de clase y un ID , la clase se calcula con un valor de 15solo, no importa cuán detallado sea.

Eso coincide con mi experiencia sobre cómo se comporta la especificidad.

Sin embargo, debe haber cierta acumulación de clases porque

.a .b .c .d .e .f .g .h .i .j .k .l .m .n .o

es más específico que

.o

La única explicación que tengo es que la especificidad de las clases apiladas se calcula solo entre sí, pero no con los ID.

Actualización : ya lo entiendo a medias. No es un sistema de puntos y la información sobre clases que pesan 15 puntos es incorrecta. Es un sistema de numeración de 4 partes muy bien explicado aquí .

El punto de partida son 4 figuras:

style  id   class element
0,     0,   0,    0

Según la explicación del W3C sobre especificidad , los valores de especificidad para las reglas mencionadas anteriormente son:

#a            0,1,0,0    = 100
classes       0,0,15,0   = ... see the comments

Este es un sistema de numeración con una base muy grande (¿indefinida?).

Tengo entendido que debido a que la base es muy grande, ningún número en la columna 4 puede vencer a un número> 0 en la columna 3, lo mismo para la columna 2, la columna 1... ¿Es correcto?

Me interesaría saber si alguien con mejores conocimientos de matemáticas que yo podría explicar el sistema de numeración y cómo convertirlo a decimal cuando los elementos individuales son mayores que 9.

Pekka avatar May 11 '2010 08:05 Pekka

El borrador de trabajo actual de Selectores de nivel 4 hace un buen trabajo al describir la especificidad en CSS:

Las especificidades se comparan comparando los tres componentes en orden: la especificidad con un valor A mayor es más específica; si los dos valores A están empatados, entonces la especificidad con un valor B mayor es más específica; si los dos valores B también están empatados, entonces la especificidad con un valor c mayor es más específica; si todos los valores están empatados, las dos especificidades son iguales.

Esto significa que los valores A, B y C son completamente independientes entre sí.

15 clases no le dan a su selector una puntuación de especificidad de 150, le dan un valor B de 15. Un solo valor A es suficiente para superar esto.

Como metáfora, imagine una familia de 1 abuelo, 1 padre y 1 hijo. Esto podría representarse como 1,1,1 . Si el padre tiene 15 hijos, eso no los convierte de repente en otro padre ( 1,2,0 ). Significa que el padre tiene mucha más responsabilidad que la que tenía con solo 1 hijo ( 1,1,15 ). ;)

La misma documentación también continúa diciendo:

Debido a limitaciones de almacenamiento, las implementaciones pueden tener limitaciones en el tamaño de A , B o c . Si es así, los valores superiores al límite deben limitarse a ese límite y no desbordarse.

Esto se agregó para abordar el problema presentado en la respuesta de Fausto , donde las implementaciones de CSS allá por 2012 permitieron que los valores de especificidad se desbordaran entre sí.

En 2012, la mayoría de los navegadores implementaron una limitación de 255, pero se permitió que esta limitación se desbordara. 255 clases tuvieron una puntuación de especificidad A,B,c de 0,255,0 , pero 256 clases se desbordaron y tuvieron una puntuación A,B,c de 1,0,0 . De repente, nuestro valor B se convirtió en nuestro valor A. La documentación de Selectors Level 4 irradia completamente ese problema al afirmar que nunca se puede permitir que el límite se desborde. Con esta implementación, las clases 255 y 256 tendrían la misma puntuación A,B,c de 0,255,0 .

Desde entonces, el problema planteado en la respuesta de Fausto se ha solucionado en la mayoría de los navegadores modernos.

James Donnelly avatar Mar 14 '2016 16:03 James Donnelly

Actualmente estoy usando el libro CSS Mastery: Advanced Web Standards Solutions .

El capítulo 1, página 16 dice:

Para calcular qué tan específica es una regla, a cada tipo de selector se le asigna un valor numérico. Luego, la especificidad de una regla se calcula sumando el valor de cada uno de sus selectores. Desafortunadamente, la especificidad no se calcula en base 10 sino en un número de base alto y no especificado. Esto es para garantizar que un selector muy específico, como un selector de ID, nunca sea anulado por muchos selectores menos específicos, como los selectores de tipo.

(el énfasis es mío) y

La especificidad de un selector se divide en cuatro niveles constituyentes: a, b, cy d.

  • si el estilo es un estilo en línea, entonces a = 1
  • b = el número total de selectores de identificación
  • c = el número de selectores de clase, pseudoclase y atributo
  • d = el número de selectores de tipo y selectores de pseudoelementos

Continúa diciendo que a menudo puedes hacer el cálculo en base 10, pero sólo si todas las columnas tienen valores inferiores a 10.


En sus ejemplos, las identificaciones no valen 100 puntos; cada uno vale [0, 1, 0, 0]puntos. Por lo tanto, una identificación supera a 15 clases porque [0, 1, 0, 0]es mayor que [0, 0, 15, 0]en un sistema numérico de base alta.

Matt Fenwick avatar Feb 16 '2012 19:02 Matt Fenwick