Details zur CSS-Spezifität

Avatar of Chris Coyier
Chris Coyier am

DigitalOcean bietet Cloud-Produkte für jede Phase Ihrer Reise. Starten Sie mit 200 $ kostenlosem Guthaben!

Lassen Sie uns dieses Thema speziell behandeln. (Trommelwirbel!)

Der beste Weg, dies zu erklären, ist, mit einem Beispiel zu beginnen, bei dem die Spezifität verwirrend wird und sich vielleicht nicht so verhält, wie Sie es erwarten würden. Dann werden wir uns genauer ansehen, wie der tatsächliche Spezifitätswert berechnet wird, um zu bestimmen, welcher Selektor Vorrang hat.

Hier ist eine einfache unsortierte Liste

<ul id="summer-drinks">
   <li>Whiskey and Ginger Ale</li>
   <li>Wheat Beer</li>
   <li>Mint Julip</li>
</ul>

Jetzt möchten Sie eines dieser Getränke als Ihr Lieblingsgetränk kennzeichnen und dessen Stil leicht ändern. Sie benötigen dafür einen Ankerpunkt, also wenden Sie ihn über einen Klassennamen auf das Listenelement an.

<ul id="summer-drinks">
   <li class="favorite">Whiskey and Ginger Ale</li>
   <li>Wheat Beer</li>
   <li>Mint Julip</li>
</ul>

Jetzt öffnen Sie Ihr CSS und gestalten Ihre neue Klasse

.favorite {
  color: red;
  font-weight: bold;
}

Dann werfen Sie einen Blick auf Ihre Arbeit, aber ach, sie hat nicht funktioniert! Der Text Ihres Lieblingsgetränks ist nicht rot oder fett geworden! Hier ist etwas Merkwürdiges am Werk.

Wenn Sie tiefer in das CSS eindringen, finden Sie dies

ul#summer-drinks li {
   font-weight: normal;
   font-size: 12px;
   color: black;
}

Da liegt Ihr Problem. Zwei verschiedene CSS-Selektoren geben diesem Text an, welche Farbe und welche Schriftstärke er haben soll. Es gibt nur eine Angabe für die Schriftgröße, also wird diese eindeutig wirksam. Das sind keine „Konflikte“ an sich, aber der Browser muss entscheiden, welche dieser Angaben er berücksichtigen soll. Dies geschieht durch Befolgen einer standardmäßigen Reihe von Spezifitätsregeln.

Ich denke, das verwirrt manche Anfänger, weil sie das noch nicht ganz sortiert haben. Sie denken vielleicht, weil die .favorite-Anweisung „weiter unten im CSS“ steht oder weil die class=”favorite” „näher am eigentlichen Text“ im HTML liegt, dass dies diejenige sein wird, die „gewinnt“.

Tatsächlich spielt die Reihenfolge der Selektoren in Ihrem CSS eine Rolle und die „weiter unten“ stehende gewinnt tatsächlich, wenn die Spezifitätswerte genau gleich sind. Zum Beispiel

.favorite {
   color: red;
}
.favorite {
   color: black;
}

Die Farbe wird schwarz sein... aber ich schweife ab.

Der Punkt ist, Sie wollen so spezifisch sein, wie es sinnvoll ist, wann immer Sie die Gelegenheit dazu haben. Selbst bei dem einfachen Beispiel oben wird es Ihnen schließlich offensichtlich werden, dass die bloße Verwendung eines Klassennamens, um dieses „Lieblingsgetränk“ anzusprechen, nicht ausreicht oder selbst wenn es funktionieren würde, nicht sehr sicher wäre. Es wäre klug gewesen, dies zu verwenden

ul#summer-drinks li.favorite {
  color: red;
  font-weight: bold;
}

Das nenne ich „so spezifisch sein, wie es sinnvoll ist“. Sie könnten tatsächlich viel spezifischer sein und etwas wie dies verwenden

html body div#pagewrap ul#summer-drinks li.favorite {
  color: red;
  font-weight: bold;
}

Aber das ist übertrieben. Es macht Ihr CSS schwerer lesbar und bringt keine wirklichen Vorteile. Eine weitere Möglichkeit, den Spezifitätswert für Ihre „.favorite“-Klasse zu erhöhen, ist die Verwendung der !important-Deklaration.

.favorite {
  color: red !important;
  font-weight: bold !important;
}

Ich habe einmal gehört, dass !important wie der Jedi-Gedankentrick für CSS ist. Tatsächlich ist es das, und Sie können Ihren Willen dem Styling von Elementen aufzwingen, indem Sie es verwenden. Aber !important erzwingt diesen Willen durch drastische Erhöhung der Spezifität der Eigenschaft dieses bestimmten Selektors.

Die !important-Deklaration kann bei Missverständnissen leicht missbraucht werden. Sie eignet sich am besten, um Ihr CSS sauberer zu halten, in Beispielen, bei denen Sie wissen, dass Elemente mit einem bestimmten Klassenselektor eine bestimmte Formatierung verwenden sollen, egal was passiert. Umgekehrt sollte sie nicht einfach als schnelle Krücke verwendet werden, um das Styling von etwas zu überschreiben, anstatt herauszufinden, wie das CSS vom ursprünglichen Autor strukturiert wurde und funktioniert hat.

Eines meiner klassischen Beispiele ist

.last {
   margin-right: 0 !important;
}

Ich benutze das oft in Situationen, in denen es mehrere gefloatete Blöcke gibt, für den letzten Block rechts in einer Reihe. Das stellt sicher, dass der letzte Block keinen rechten Rand hat, der ihn davon abhalten würde, eng an die rechte Kante seines Elternteils zu stoßen. Jeder dieser Blöcke hat wahrscheinlich spezifischere CSS-Selektoren, die den rechten Rand von vornherein zuweisen, aber !important bricht dadurch und kümmert sich mit einer einfachen/sauberen Klasse darum.

Berechnung des CSS-Spezifitätswerts

Warum ist unser erster Versuch, die Farbe und Schriftstärke zu ändern, fehlgeschlagen? Wie wir gelernt haben, lag es daran, dass die bloße Verwendung des Klassennamens allein einen geringeren Spezifitätswert hatte und von dem anderen Selektor übertrumpft wurde, der die unsortierte Liste mit dem ID-Wert ansprach. Die wichtigen Wörter in diesem Satz waren Klasse und ID. CSS weist Klassen und IDs stark unterschiedliche Spezifitätsgewichte zu. Tatsächlich hat eine ID einen unendlich höheren Spezifitätswert! Das heißt, keine Anzahl von Klassen allein kann eine ID ausgleichen.

Werfen wir einen Blick darauf, wie die Zahlen tatsächlich berechnet werden

Anders ausgedrückt

  • Wenn das Element eine Inline-Formatierung hat, gewinnt diese automatisch1 (1.000 Punkte)
  • Für jeden ID-Wert werden 0,1,0,0 Punkte vergeben
  • Für jeden Klassenwert (oder Pseudoklasse oder Attributselektor) werden 0,0,1,0 Punkte vergeben
  • Für jede Elementreferenz werden 0,0,0,1 Punkt vergeben

Sie können die Werte im Allgemeinen so lesen, als wären sie einfach eine Zahl, wie 1.000,0,0 „1000“ ist und daher eindeutig über einer Spezifität von 0,1,0,0 oder „100“ gewinnt. Die Kommas sind dazu da, uns daran zu erinnern, dass dies kein „Basis-10“-System ist, insofern Sie technisch einen Spezifitätswert von z. B. 0,1,13,4 haben könnten – und diese „13“ nicht überläuft, wie es ein Basis-10-System tun würde.

Beispielberechnungen



Update: Die :not()-Pseudo-Klasse fügt keinen eigenen Spezifitätswert hinzu, nur das Innere der Klammern wird zum Spezifitätswert addiert.



Wichtige Hinweise

  • Der universelle Selektor (*) hat keinen Spezifitätswert (0,0,0,0)
  • Pseudo-Elemente (z. B. :first-line) erhalten 0,0,0,1 im Gegensatz zu ihren Pseudo-Klassen-Geschwistern, die 0,0,1,0 erhalten.
  • Die Pseudo-Klasse :not() fügt selbst keine Spezifität hinzu, nur das, was sich in ihren Klammern befindet.
  • Der Wert !important, der an einen CSS-Eigenschaftswert angehängt wird, ist ein automatischer Gewinn. Er überschreibt sogar Inline-Stile aus dem Markup. Der einzige Weg, wie ein !important-Wert überschrieben werden kann, ist eine weitere !important-Regel, die später in der CSS mit gleicher oder höherer Spezifität deklariert wird, andernfalls. Sie könnten es sich so vorstellen, als ob Sie der Spezifität 1.000.000 hinzu fügen würden.

Ressourcen