Come vengono calcolati i punti nella specificità CSS


125

Facendo ricerche sulla specificità mi sono imbattuto in questo blog - http://www.htmldog.com/guides/cssadvanced/specificity/

Afferma che la specificità è un sistema di punteggio per i CSS. Ci dice che gli elementi valgono 1 punto, le classi valgono 10 punti e gli ID valgono 100 punti. Va anche detto che questi punti sono sommati e l'importo complessivo è la specificità di quel selettore.

Per esempio:

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

Quindi, usando questi punti, mi aspetto che i seguenti CSS e HTML risultino nel testo blu:

#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>

Perché il testo è rosso quando 15 classi equivalgono a 150 punti rispetto a 1 ID che equivale a 100 punti?

Apparentemente i punti non sono solo sommati; sono concatenati. Leggi di più su questo qui - http://www.stuffandnonsense.co.uk/archives/css_specificity_wars.html

Ciò significa che le classi nel nostro selettore = 0,0,15,0OR 0,1,5,0?

(Il mio istinto mi dice che è il primo, poiché SAPPIAMO che la specificità del selettore di ID è simile a questa 0,1,0,0:)


Anche qui c'è qualcosa di strano: stackoverflow.com/questions/25565928/…
Armel Larcier,

Risposte:


138

La risposta di Pekka è praticamente corretta e probabilmente il modo migliore per pensare al problema.

Tuttavia, come molti hanno già sottolineato, la raccomandazione CSS del W3C afferma che "la concatenazione dei tre numeri abc (in un sistema numerico con una base ampia) fornisce la specificità". Quindi il disadattato dentro di me doveva solo capire quanto fosse grande questa base.

Risulta che la "base molto ampia" impiegata (almeno dai 4 browser più comunemente usati * ) per implementare questo algoritmo standard è 256 o 2 8 .

Ciò significa che uno stile specificato con 0 ID e 256 di classe nomi sarà over-ride uno stile specificato con solo 1 id. L'ho provato con alcuni violini:

Quindi esiste, effettivamente, un "sistema a punti", ma non è la base 10. È la base 256. Ecco come funziona:

(2 8 ) 2 o 65536, per il numero di ID nel selettore
+ (2 8 ) 1 o 256, per il numero di nomi di classe nel selettore
+ (2 8 ) 0 o 1, per il numero di tag- nomi nel selettore

Questo non è molto pratico per gli esercizi back-of-the-bus per comunicare il concetto.
Questo è probabilmente il motivo per cui gli articoli sull'argomento hanno utilizzato la base 10.

***** [Opera usa 2 16 (vedi il commento di karlcow). Alcuni altri motori di selezione usano l' infinito , in effetti nessun sistema di punti (vedi il commento di Simon Sapin).]

Aggiornamento, luglio 2014:
come Blazemonger ha sottolineato all'inizio dell'anno, i browser webkit (chrome, safari) ora sembrano utilizzare una base superiore a 256. Forse 2 16 , come Opera? IE e Firefox usano ancora 256.


34
Importante: nota che il numero 256 non è nelle specifiche . Pertanto, questa risposta descrive un dettaglio di implementazione (certamente utile).
Matt Fenwick

6
Non solo 256 non è nelle specifiche come ha detto @MattFenwick, ma varia anche a seconda dell'implementazione. Apparentemente è più grande in Opera. In WeasyPrint e cssselect è "infinity": utilizzo una tupla di interi invece di un singolo intero.
Simon Sapin

3
@ Faust opera usa 16 bit invece di 8
karlcow

4
Questa risposta ha una descrizione più pratica della risposta di Pekka, ad essere onesti. Fondamentalmente quello che dice @Matt Fenwick: quello che stai descrivendo è un'implementazione pratica delle specifiche. Un difetto in questo, ma non qualcosa per cui dovrebbe essere fatto nulla, sia da autori che da implementatori.
BoltClock

7
256 sembra essere insufficiente nelle attuali versioni di webkit (Chrome e Safari), sottolineando ulteriormente il punto di @ MattFenwick.
Blazemonger

28

Buona domanda.

Non posso dirlo con certezza - tutti gli articoli che riesco a trovare evitano l'esempio di più classi, ad esempio qui - ma presumo che quando si tratta di confrontare la specificità tra un selettore di classe e un ID , la classe viene calcolata con un valore di 15solo, non importa quanto sia dettagliato.

Ciò corrisponde alla mia esperienza su come si comporta la specificità.

Tuttavia, ci deve essere un certo impilamento di classi perché

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

è più specifico di

.o

l'unica spiegazione che ho è che la specificità delle classi in pila viene calcolata solo l'una rispetto all'altra ma non rispetto agli ID.

Aggiornamento : ho capito a metà ora. Non è un sistema a punti e le informazioni sulle classi che pesano 15 punti non sono corrette. È un sistema di numerazione in 4 parti spiegato molto bene qui .

Il punto di partenza sono 4 cifre:

style  id   class element
0,     0,   0,    0

Secondo la spiegazione del W3C sulla specificità , i valori di specificità per le regole di cui sopra sono:

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

questo è un sistema di numerazione con una base molto grande (indefinita?).

La mia comprensione è che poiché la base è molto grande, nessun numero nella colonna 4 può battere un numero> 0 nella colonna 3, lo stesso per la colonna 2, colonna 1 .... È corretto?

Sarei interessato se qualcuno con una conoscenza migliore della matematica di me potesse spiegare il sistema di numerazione e come convertirlo in decimale quando i singoli elementi sono più grandi di 9.


Questo perché è tra .o e .a .b ecc. Quindi li considererebbe collettivamente. Ma tra un ID e una classe, ad esempio: .a e #a, l'ID avrà sempre la meglio. Conterà (presumo) solo tra le classi quando non c'è un attr più potente. Ad esempio, la classe passerà all'elemento e l'ID alla classe.
Sphvn

@Ozaki è quello che presumo anch'io, ma contraddice ciò che l'OP sta dicendo sul sistema a punti. Deve esserci di più in gioco. Mi piacerebbe vedere le regole che ci stanno dietro.
Pekka

Mi sono appena reso conto che siamo entrambi arrivati ​​alla stessa conclusione. Lavoro eccellente!
Sam

5
Per quanto riguarda la matematica, qui possiamo lavorare in base 16 (perché nessuno dei numeri individuali supera 15). Quindi 0,1,0,0 = 0100h = 256 0,0,15,0 = 00f0h = 240256> 240 quindi il selettore di id vince.
Matthew Wilson,

1
Sì, puoi pensare che i calcoli di specificità vengano eseguiti in un sistema numerico con una base ampia. Penso che il termine "concatenazione" (usato anche nelle specifiche) sia una descrizione molto migliore. (Sono venuto qui per aver risposto a una nuova domanda che si rivela essere una vittima di questa, vai a capire ...)
BoltClock

9

L'attuale bozza di lavoro del livello 4 dei selettori fa un buon lavoro nel descrivere la specificità nei CSS:

Le specificità vengono confrontate confrontando le tre componenti in ordine: la specificità con un valore A maggiore è più specifica; se i due valori A sono legati, la specificità con un valore B maggiore è più specifica; se anche i due valori B sono legati, la specificità con un valore c maggiore è più specifica; se tutti i valori sono pari, le due specificità sono uguali.

Ciò significa che i valori A, B e C sono completamente indipendenti l'uno dall'altro.

15 classi non danno al tuo selettore un punteggio di specificità di 150, gli dà un valore B di 15. Un singolo valore A è sufficiente per sopraffarlo.

Come metafora, immagina una famiglia di 1 nonno, 1 genitore e 1 bambino. Questo potrebbe essere rappresentato come 1,1,1 . Se il genitore ha 15 figli, ciò non li rende improvvisamente un altro genitore ( 1,2,0 ). Significa che il genitore ha molta più responsabilità di quella che aveva con un solo figlio ( 1,1,15 ). ;)

La stessa documentazione prosegue anche dicendo:

A causa delle limitazioni di archiviazione, le implementazioni potrebbero avere limitazioni sulle dimensioni di A , B o c . In tal caso, i valori superiori al limite devono essere limitati a tale limite e non eccedenti.

Questo è stato aggiunto per affrontare il problema presentato nella risposta di Faust , per cui le implementazioni CSS nel 2012 consentivano ai valori di specificità di traboccare l'uno nell'altro.

Nel 2012, la maggior parte dei browser implementava una limitazione di 255, ma a questa limitazione era consentito l'overflow. 255 classi avevano un punteggio di specificità A, B, c di 0,255,0 , ma 256 classi erano in overflow e avevano un punteggio A, B, c di 1,0,0 . All'improvviso il nostro valore B è diventato il nostro valore A. La documentazione di Selectors Level 4 irradia completamente questo problema affermando che il limite non può mai essere consentito di traboccare. Con questa implementazione, entrambe le classi 255 e 256 avrebbero lo stesso punteggio A, B, c di 0,255,0 .

Il problema dato nella risposta di Faust da allora è stato risolto nella maggior parte dei browser moderni.


8

Attualmente sto utilizzando il libro CSS Mastery: Advanced Web Standards Solutions .

Il capitolo 1, pagina 16 dice:

Per calcolare quanto sia specifica una regola, a ogni tipo di selettore viene assegnato un valore numerico. La specificità di una regola viene quindi calcolata sommando il valore di ciascuno dei suoi selettori. Sfortunatamente, la specificità non è calcolata in base 10 ma un numero di base elevato, non specificato. Questo per garantire che un selettore altamente specifico, come un selettore ID, non venga mai sovrascritto da molti selettori meno specifici, come i selettori di tipo.

(enfasi mia) e

La specificità di un selettore è suddivisa in quattro livelli costituenti: a, b, c e d.

  • se lo stile è uno stile in linea, allora a = 1
  • b = il numero totale di selettori di id
  • c = il numero di selettori di classe, pseudo-classe e attributo
  • d = il numero di selettori di tipo e selettori di pseudo-elementi

Continua dicendo che spesso puoi fare il calcolo in base 10, ma solo se tutte le colonne hanno valori inferiori a 10.


Nei tuoi esempi, gli ID non valgono 100 punti; ognuno vale [0, 1, 0, 0]punti. Pertanto, un ID batte 15 classi perché [0, 1, 0, 0]è maggiore rispetto [0, 0, 15, 0]a un sistema di numeri a base alta.


4

Adoro il confronto tra la classifica della specificità e la medaglia dei Giochi Olimpici (metodo gold first - basato prima sul numero di medaglie d'oro, poi d'argento e poi di bronzo).

Funziona anche con la tua domanda (numero enorme di selettori in un gruppo di specificità). La specificità ha considerato ogni gruppo separatamente. Nel mondo reale ho visto molto raramente case con più di una dozzina di selettori).

C'è anche un calcolatore di specificità abbastanza buono disponibile qui . Puoi inserire il tuo esempio (#a e .a .b .c .d .e .f .g .h .i .j .k .l .m .n .o) e vedere i risultati.

Esempio di medaglia dei Giochi Olimpici di Rio 2016 sembra inserisci qui la descrizione dell'immagine


3

Non credo che la spiegazione del blog sia corretta. La specifica è qui:

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

I "punti" di un selettore di classe non possono sommarsi per essere più importanti di un selettore di "id". Semplicemente non funziona così.


Come ho detto nella mia risposta. ^^ Comunque fa la differenza se ne hai più dello stesso tipo (elemento, classe, id). Ma questo è abbastanza ovvio se 5 ° dicono rosso e 3 dicono blu, beh Ima diventa rosso.
Sphvn

La formulazione sulla specificità probabilmente non è cambiata molto tra CSS2 e CSS2.1, ma dovresti davvero puntare alla specifica CSS2.1 nelle discussioni future in quanto sostituisce completamente CSS2 che in generale era rotto al momento del rilascio.
Robin Whittleton

1

Direi che:

Element < Class < ID

Penso che si accumulino solo in base a ciò che ottieni se è multiplo dello stesso. Quindi una Classe sovrascriverà sempre l'elemento e l'ID sempre sopra la Classe, ma se dipende da quale dei 4 elementi dove 3 sta al blu e 1 sta al rosso, sarà blu.

Per esempio:

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

 .m .n .o
{
color blue;
}

Dovrebbe diventare rosso.

Vedi Esempio http://jsfiddle.net/RWFWq/

"se 5 ° dicono rosso e 3 dicono blu, beh Ima diventa rosso"

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.