Wie werden die Punkte in der CSS-Spezifität berechnet?

124

Nach Recherchen zur Spezifität bin ich auf diesen Blog gestoßen - http://www.htmldog.com/guides/cssadvanced/specificity/

Es heißt, dass Spezifität ein Punktesystem für CSS ist. Es sagt uns, dass Elemente 1 Punkt wert sind, Klassen 10 Punkte wert sind und IDs 100 Punkte wert sind. Es heißt auch, dass diese Punkte summiert werden und der Gesamtbetrag die Spezifität des Selektors ist.

Beispielsweise:

body = 1 Punkt
body .wrapper = 11 Punkte
body .wrapper #container = 111 Punkte

Wenn ich diese Punkte verwende, erwarte ich, dass das folgende CSS und HTML dazu führt, dass der Text blau ist:

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

Warum ist der Text rot, wenn 15 Klassen 150 Punkte im Vergleich zu 1 ID entsprechen, was 100 Punkten entspricht?

Anscheinend werden die Punkte nicht nur summiert; Sie sind verkettet. Lesen Sie hier mehr darüber - http://www.stuffandnonsense.co.uk/archives/css_specificity_wars.html

Bedeutet das, dass die Klassen in unserem Selektor = 0,0,15,0ODER sind 0,1,5,0?

(mein Instinkt sagt mir , es ist die ehemalige, wie wir die ID - Auswahl der Spezifität wie folgt aussehen wissen: 0,1,0,0)

Sam
quelle
Hier ist auch etwas Seltsames: stackoverflow.com/questions/25565928/…
Armel Larcier

Antworten:

137

Pekkas Antwort ist praktisch richtig und wahrscheinlich die beste Art, über das Problem nachzudenken.

Wie viele bereits betont haben, heißt es in der W3C-CSS-Empfehlung jedoch: "Die Verkettung der drei Zahlen abc (in einem Zahlensystem mit großer Basis) ergibt die Spezifität." Also musste der Geek in mir nur herausfinden, wie groß diese Basis ist.

Es stellt sich heraus, dass die "sehr große Basis", die (zumindest von den 4 am häufigsten verwendeten Browsern * ) zur Implementierung dieses Standardalgorithmus verwendet wird, 256 oder 2 8 beträgt .

Was dies bedeutet , ist , dass ein Stil mit 0 IDs angegeben und 256 Klassennamen wird eine Art mit nur 1 - ID angegeben over-ride. Ich habe das mit ein paar Geigen getestet:

Es gibt also effektiv ein "Punktesystem", aber es ist nicht Basis 10. Es ist Basis 256. So funktioniert es:

(2 8 ) 2 oder 65536, mal die Anzahl der IDs im Selektor
+ (2 8 ) 1 oder 256, mal die Anzahl der Klassennamen im Selektor
+ (2 8 ) 0 oder 1, mal die Anzahl der Tag- Namen in der Auswahl

Dies ist nicht sehr praktisch für Übungen auf der Rückseite des Umschlags, um das Konzept zu kommunizieren.
Das ist wahrscheinlich der Grund, warum Artikel zu diesem Thema Base 10 verwenden.

***** [Opera verwendet 2 16 (siehe Karlcows Kommentar). Einige andere Selektor-Engines verwenden Infinity - praktisch kein Punktesystem (siehe Simon Sapins Kommentar).]

Update, Juli 2014:
Wie Blazemonger Anfang des Jahres betonte, scheinen Webkit-Browser (Chrome, Safari) jetzt eine höhere Basis als 256 zu verwenden. Vielleicht 2 16 , wie Opera? IE und Firefox verwenden immer noch 256.

Faust
quelle
34
Wichtig: Beachten Sie, dass die Nummer 256 nicht in der Spezifikation enthalten ist . Somit beschreibt diese Antwort ein (zugegebenermaßen nützliches) Implementierungsdetail.
Matt Fenwick
6
Nicht nur 256 ist nicht in der Spezifikation enthalten, wie @MattFenwick sagte, sondern es variiert auch je nach Implementierung. In Opera ist es anscheinend größer. In WeasyPrint und cssselect ist es "unendlich": Ich verwende ein Tupel von ganzen Zahlen anstelle einer einzelnen ganzen Zahl.
Simon Sapin
3
@Faust Oper verwendet 16 Bit anstelle von 8
Karlcow
4
Diese Antwort hat eine praktischere Beschreibung als Pekkas Antwort, um ehrlich zu sein. Grundsätzlich sagt @Matt Fenwick: Was Sie beschreiben, ist eine praktische Implementierung der Spezifikation. Eine fehlerhafte, aber keine, gegen die etwas unternommen werden sollte, sei es von Autoren oder Implementierern.
BoltClock
7
256 scheint in aktuellen Versionen des Webkits (Chrome und Safari) nicht ausreichend zu sein, was den Punkt von @ MattFenwick weiter unterstreicht.
Blazemonger
28

Gute Frage.

Ich kann nicht sicher sagen - alle Artikel, die ich finde, vermeiden das Beispiel mehrerer Klassen, z. B. hier -, aber ich gehe davon aus, dass beim Vergleich der Spezifität zwischen einem Klassenselektor und einer ID die Klasse mit a berechnet wird Wert von 15nur, egal wie detailliert es ist.

Das entspricht meiner Erfahrung mit dem Verhalten von Spezifität.

Es muss jedoch einige Stapel von Klassen geben, weil

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

ist spezifischer als

.o

Die einzige Erklärung, die ich habe, ist, dass die Spezifität gestapelter Klassen nur gegeneinander berechnet wird, nicht aber gegen IDs.

Update : Ich bekomme es jetzt auf halbem Weg. Es ist kein Punktesystem, und die Informationen zu Klassen mit einem Gewicht von 15 Punkten sind falsch. Es ist ein 4-teiligen Nummerierungssystem sehr gut erklärt hier .

Der Ausgangspunkt ist 4 Zahlen:

style  id   class element
0,     0,   0,    0

Gemäß der W3C-Erklärung zur Spezifität sind die Spezifitätswerte für die oben genannten Regeln:

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

Dies ist ein Nummerierungssystem mit einer sehr großen (undefinierten?) Basis.

Mein Verständnis ist, dass, weil die Basis sehr groß ist, keine Zahl in Spalte 4 eine Zahl> 0 in Spalte 3 schlagen kann, dasselbe gilt für Spalte 2, Spalte 1 ... Ist das richtig?

Es würde mich interessieren, ob jemand mit einem besseren Verständnis von Mathematik als ich das Nummerierungssystem erklären könnte und wie man es in Dezimalzahlen umwandelt, wenn die einzelnen Elemente größer als 9 sind.

Pekka
quelle
Das liegt daran, dass es zwischen .o & .a .b usw. liegt. Also würde es sie gemeinsam betrachten. Aber zwischen einer ID und einer Klasse, zB: .a und #a, wird die ID immer überwältigen. Es wird (ich nehme an) nur zwischen Klassen zählen, wenn es kein überwältigenderes attr gibt. ZB Klasse geht über Element und ID über Klasse.
Sphvn
@ Ozaki das nehme ich auch an, aber es widerspricht dem, was das OP über das Punktesystem sagt. Es muss mehr im Spiel sein. Ich würde gerne die Regeln dahinter sehen.
Pekka
Ich habe gerade festgestellt, dass wir beide zu dem gleichen Schluss gekommen sind. Ausgezeichnete Arbeit!
Sam
5
Für die mathematische Seite können wir hier in Basis 16 arbeiten (da keine der einzelnen Zahlen 15 überschreitet). Also 0,1,0,0 = 0100h = 256 0,0,15,0 = 00f0h = 240 256> 240, damit der ID-Selektor gewinnt.
Matthew Wilson
1
Ja, Sie können sich Spezifitätsberechnungen in einem Zahlensystem mit einer großen Basis vorstellen. Ich denke, der Begriff "Verketten" (auch in der Spezifikation verwendet) ist jedoch eine viel bessere Beschreibung. (Kam hierher von der Beantwortung einer neuen Frage, die sich als Betrug dieser herausstellt, siehe Abbildung ...)
BoltClock
9

Der aktuelle Selectors Level 4 Working Draft beschreibt die Spezifität in CSS gut:

Die Spezifitäten werden verglichen, indem die drei Komponenten der Reihe nach verglichen werden: Die Spezifität mit einem größeren A- Wert ist spezifischer; Wenn die beiden A- Werte gebunden sind, ist die Spezifität mit einem größeren B- Wert spezifischer. Wenn die beiden B- Werte auch gebunden sind, ist die Spezifität mit einem größeren c- Wert spezifischer. Wenn alle Werte gebunden sind, sind die beiden Spezifitäten gleich.

Dies bedeutet, dass die Werte A, B und C völlig unabhängig voneinander sind.

15 Klassen geben Ihrem Selektor keine Spezifitätsbewertung von 150, sondern einen B- Wert von 15. Ein einzelner A- Wert reicht aus, um dies zu überwältigen.

Stellen Sie sich als Metapher eine Familie mit 1 Großelternteil, 1 Elternteil und 1 Kind vor. Dies könnte als 1,1,1 dargestellt werden . Wenn der Elternteil 15 Kinder hat, werden sie nicht plötzlich zu einem anderen Elternteil ( 1,2,0 ). Dies bedeutet, dass die Eltern sehr viel mehr Verantwortung tragen als mit nur einem Kind ( 1,1,15 ). ;)

In derselben Dokumentation heißt es auch:

Aufgrund von Speicherbeschränkungen können Implementierungen Einschränkungen hinsichtlich der Größe von A , B oder c aufweisen . In diesem Fall müssen Werte über dem Grenzwert an diesen Grenzwert geklemmt werden und dürfen nicht überlaufen.

Dies wurde hinzugefügt, um das in Fausts Antwort dargestellte Problem anzugehen , bei dem CSS-Implementierungen im Jahr 2012 das Überlaufen von Spezifitätswerten ineinander ermöglichten.

Im Jahr 2012 haben die meisten Browser eine Einschränkung von 255 implementiert, die jedoch überlaufen durfte. 255 Klassen hatten einen A, B, c- Spezifitätswert von 0,255,0 , aber 256 Klassen liefen über und hatten einen A, B, c- Wert von 1,0,0 . Plötzlich wurde unser B- Wert unser A- Wert. In der Selectors Level 4-Dokumentation wird dieses Problem vollständig beleuchtet, indem angegeben wird, dass der Grenzwert niemals überlaufen darf. Mit dieser Implementierung hätten sowohl 255 als auch 256 Klassen den gleichen A-, B-, c- Wert von 0,255,0 .

Das in Fausts Antwort angegebene Problem wurde inzwischen in den meisten modernen Browsern behoben .

James Donnelly
quelle
8

Ich verwende derzeit das Buch CSS Mastery: Advanced Web Standards Solutions .

Kapitel 1, Seite 16 sagt:

Um zu berechnen, wie spezifisch eine Regel ist, wird jedem Auswahltyp ein numerischer Wert zugewiesen. Die Spezifität einer Regel wird dann berechnet, indem der Wert jedes ihrer Selektoren addiert wird. Leider wird die Spezifität nicht in Basis 10 berechnet, sondern in einer hohen, nicht spezifizierten Basiszahl. Dies soll sicherstellen, dass ein hochspezifischer Selektor, wie z. B. ein ID-Selektor, niemals von vielen weniger spezifischen Selektoren, wie z. B. Typselektoren, überschrieben wird.

(Hervorhebung von mir) und

Die Spezifität eines Selektors ist in vier Bestandteile unterteilt: a, b, c und d.

  • Wenn der Stil ein Inline-Stil ist, ist a = 1
  • b = die Gesamtzahl der ID-Selektoren
  • c = Anzahl der Klassen-, Pseudoklassen- und Attributselektoren
  • d = Anzahl der Typselektoren und Pseudoelementselektoren

Es heißt weiter, dass Sie die Berechnung häufig in Basis 10 durchführen können, jedoch nur, wenn alle Spalten Werte unter 10 haben.


In Ihren Beispielen sind IDs nicht 100 Punkte wert. Jeder ist [0, 1, 0, 0]Punkte wert . Daher schlägt eine ID 15 Klassen, weil sie [0, 1, 0, 0]größer ist als [0, 0, 15, 0]in einem System mit hoher Basiszahl.

Matt Fenwick
quelle
4

Ich mag den Vergleich des Spezifitätsrankings mit der Medaillentabelle der Olympischen Spiele (Gold zuerst - zuerst basierend auf der Anzahl der Goldmedaillen, dann Silber und dann Bronze).

Es funktioniert auch mit Ihrer Frage (große Anzahl von Selektoren in einer Spezifitätsgruppe). Spezifität betrachtet jede Gruppe separat. In der realen Welt habe ich sehr selten Fälle mit mehr als einem Dutzend Selektoren gesehen.

Es ist auch recht gut Spezifität Rechner verfügbar hier . Sie können dort Ihr Beispiel (#a und .a .b .c .d .e .f .g .h .i .j .k .l .m .n .o) einfügen und die Ergebnisse anzeigen.

Ein Beispiel für die Medaillentabelle der Olympischen Spiele 2016 in Rio sieht aus Geben Sie hier die Bildbeschreibung ein

rkarczmarczyk
quelle
3

Ich glaube nicht, dass die Erklärung des Blogs richtig ist. Die Spezifikation ist hier:

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

"Punkte" aus einem Klassenselektor können nicht wichtiger sein als ein "ID" -Selektor. So funktioniert es einfach nicht.

Matthew Wilson
quelle
Wie ich in meiner Antwort sagte. ^^ Es macht jedoch einen Unterschied, ob Sie mehr vom gleichen Typ haben (Element, Klasse, ID). Aber das ist ziemlich offensichtlich, wenn Fünftel Rot und 3 Blau sagen. Ima wird rot.
Sphvn
Der Wortlaut um die Spezifität hat sich zwischen CSS2 und CSS2.1 wahrscheinlich nicht wesentlich geändert, aber Sie sollten in zukünftigen Diskussionen wirklich auf die CSS2.1-Spezifikation verweisen, da sie CSS2, das zum Zeitpunkt der Veröffentlichung im Allgemeinen fehlerhaft war, vollständig ersetzt.
Robin Whittleton
1

Ich würde sagen, dass:

Element < Class < ID

Ich denke, sie stapeln sich nur in Abhängigkeit davon, was Sie bekommen, wenn es ein Vielfaches davon ist. Eine Klasse überschreibt also immer das Element und die ID immer über der Klasse, aber wenn es darauf ankommt, welches von 4 Elementen 3 zu blau und 1 zu rot ist, ist es blau.

Beispielsweise:

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

 .m .n .o
{
color blue;
}

Sollte rot ausfallen.

Siehe Beispiel http://jsfiddle.net/RWFWq/

"Wenn 5things Rot und 3 Blau sagen, werde ich rot."

Sphvn
quelle