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

124

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

Establece 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 ID valen 100 puntos. También va en la parte superior decir que estos puntos se suman y la cantidad total es la especificidad de ese selector.

Por ejemplo:

body = 1 punto
body .wrapper = 11 puntos
body .wrapper #container = 111 puntos

Entonces, usando estos puntos, espero que los siguientes 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>

¿Por qué el texto es rojo cuando 15 clases equivalen a 150 puntos en comparación con 1 ID que equivale a 100 puntos?

Aparentemente, los puntos no solo 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 el primero, como sabemos miradas especificidad del selector ID como esto: 0,1,0,0)

Sam
fuente
Aquí también hay algo extraño: stackoverflow.com/questions/25565928/…
Armel Larcier

Respuestas:

137

La respuesta de Pekka es prácticamente correcta, y probablemente 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 de números con una base grande) da la especificidad". Entonces el geek en mí solo tenía que descubrir cuán 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 y 256 identificadores de nombres de clase va a pasar por encima de un estilo especificado con sólo 1 Identificación. Probé esto con algunos violines:

Entonces, efectivamente, hay un "sistema de puntos", pero no es la base 10. Es la 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 etiquetas nombres en el selector

Esto no es muy práctico para los ejercicios al final de la envoltura para comunicar el concepto.
Probablemente por eso los artículos sobre el tema han estado utilizando la base 10.

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

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

Fausto
fuente
34
Importante: tenga en cuenta que el número 256 no está en la especificación . Por lo tanto, esta respuesta describe un detalle de implementación (ciertamente útil).
Matt Fenwick
66
No solo 256 no está en la especificación como dijo @MattFenwick, sino que también varía según la implementación. Aparentemente es más grande en Opera. En WeasyPrint y cssselect es "infinito": uso una tupla de enteros en lugar de un solo entero.
Simon Sapin
3
@Faust opera utiliza 16 bits en lugar de 8
karlcow
44
Esta respuesta tiene una descripción más práctica que la respuesta de Pekka, para ser honesto. Básicamente lo que dice @Matt Fenwick: lo que estás describiendo es una implementación práctica de la especificación. Un defecto en eso, pero no uno por el que se deba hacer nada, ya sea por autores o implementadores.
BoltClock
77
256 parece ser insuficiente en las versiones actuales de webkit (Chrome y Safari), lo que subraya aún más el punto de @ MattFenwick.
Blazemonger
28

Buena pregunta.

No puedo decir con certeza, todos los artículos que consigo encontrar evitan el ejemplo de varias clases, por ejemplo, aquí , pero supongo que cuando se trata de comparar la especificidad entre un selector de clase y una ID , la clase se calcula con un valor de 15solo, no importa cuán detallado sea.

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

Sin embargo, debe haber algún apilamiento 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 contra los ID.

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

El punto de partida es de 4 cifras:

style  id   class element
0,     0,   0,    0

De acuerdo con 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?).

Entiendo 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, columna 1 ... ¿Es esto correcto?

Me interesaría si alguien con una mejor comprensión de las 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
fuente
Eso es porque está entre .o & .a .b, etc. Así que los consideraría colectivamente. Pero entre una ID y una clase, por ejemplo: .a y #a la ID siempre dominará. (Supongo) solo contará entre clases cuando no haya un atributo más abrumador. Por ejemplo, la clase irá sobre el elemento y la identificación sobre la clase.
Sphvn
@Ozaki, eso es lo que también estoy asumiendo, pero contradice lo que dice el OP sobre el sistema de puntos. Debe haber más en juego. Me gustaría ver las reglas detrás de esto.
Pekka
Me acabo de dar cuenta de que ambos hemos llegado a la misma conclusión. ¡Excelente trabajo!
Sam
55
Para el lado de las matemáticas, podemos trabajar en la base 16 aquí (porque ninguno de los números individuales excede 15). Entonces 0,1,0,0 = 0100h = 256 0,0,15,0 = 00f0h = 240 256> 240 para que gane el selector de id.
Matthew Wilson
1
Sí, puede pensar que los cálculos de especificidad se realizan en un sistema numérico con una gran base. Sin embargo, creo que el término "concatenación" (también utilizado en la especificación) es una descripción mucho mejor. (Vine aquí al responder una nueva pregunta que resulta ser una tonta de esta,
imagínese
9

El borrador de trabajo actual de Selectores 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 vinculados, entonces la especificidad con un valor B mayor es más específica; si los dos valores B también están vinculados, entonces la especificidad con un valor c más grande es más específica; Si todos los valores están vinculados, 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 da un valor B de 15. Un solo valor A es suficiente para dominar 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 los padres tienen mucha más responsabilidad que la que tenían con solo 1 hijo ( 1,1,15 ). ;)

La misma documentación también dice:

Debido a las 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 fijarse a ese límite y no desbordarse.

Esto se ha agregado para abordar el problema presentado en la respuesta de Faust , mediante el cual las implementaciones de CSS en 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 un puntaje de especificidad A, B, c de 0,255,0 , pero 256 clases se desbordaron y tuvieron un puntaje A, B, c de 1,0,0 . De repente, nuestro valor B se convirtió en nuestro valor A. La documentación del Selector Nivel 4 irradia completamente ese problema al afirmar que nunca se puede permitir que el límite se desborde. Con esta implementación, ambos 255 y 256 clases tendrían el mismo A, B, C puntuación de 0,255,0 .

El problema dado en la respuesta de Fausto se ha solucionado en la mayoría de los navegadores modernos.

James Donnelly
fuente
8

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

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

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

(énfasis mío) y

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

  • si el estilo es un estilo en línea, entonces a = 1
  • b = el número total de selectores de id
  • 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 puede hacer el cálculo en base 10, pero solo si todas las columnas tienen valores inferiores a 10.


En sus ejemplos, los identificadores no valen 100 puntos; cada uno vale [0, 1, 0, 0]puntos. Por lo tanto, una identificación supera 15 clases porque [0, 1, 0, 0]es mayor que [0, 0, 15, 0]en un sistema de números de base alta.

Matt Fenwick
fuente
4

Me gusta comparar la clasificación de especificidad con la tabla de medallas de los Juegos Olímpicos (primer método de oro, basado primero en el número de medallas de oro, luego de plata y luego de bronce).

Funciona también con su pregunta (gran cantidad de selectores en un grupo de especificidad). La especificidad considera cada grupo por separado. En el mundo real, rara vez he visto casos con más de una docena de selectores).

También hay una calculadora de especificidad bastante buena disponible aquí . Puede poner su ejemplo (#a y .a .b .c .d .e .f .g .h .i .j .k .l .m .n .o) allí y ver los resultados.

Ejemplo de la tabla de medallas de los Juegos Olímpicos de Río 2016 se parece a ingrese la descripción de la imagen aquí

rkarczmarczyk
fuente
3

No creo que la explicación del blog sea correcta. La especificación está aquí:

http://www.w3.org/TR/CSS2/cascade.html#specificity

Los "puntos" de un selector de clase no pueden sumar más que un selector de "id". Simplemente no funciona así.

Matthew Wilson
fuente
Como dije en mi respuesta. ^^ Sin embargo, hace una diferencia si tienes más del mismo tipo (elemento, clase, id). Pero eso es bastante obvio si los 5tos dicen rojo y 3 dicen azul bien. Ima se pone rojo.
Sphvn
La redacción en torno a la especificidad probablemente no ha cambiado mucho entre CSS2 y CSS2.1, pero realmente debería apuntar a la especificación CSS2.1 en futuras discusiones, ya que reemplaza por completo a CSS2, que en general se rompió en el momento del lanzamiento.
Robin Whittleton
1

Yo diría que:

Element < Class < ID

Creo que solo se acumulan dependiendo de lo que obtienes si es múltiplo de lo mismo. Por lo tanto, una clase siempre anulará el elemento y la ID siempre sobre la clase, pero si depende de cuál de los 4 elementos, donde 3 es azul y 1 es rojo, será azul.

Por ejemplo:

.a .b .c .d .e .f .g .h .i .j .k .l
{
color: red;
}

 .m .n .o
{
color blue;
}

Debería salir rojo.

Ver ejemplo http://jsfiddle.net/RWFWq/

"si las quintas dicen rojo y 3 dicen azul bien, yo me pongo rojo"

Sphvn
fuente