Spezifität - oder "warum spinnt mein CSS?"

Wie entscheidet ein Browser, welchen Wert er verwenden soll, wenn einem Attribut mehrmals unterschiedliche Werte zugewiesen wurden?

Mittels eines Punktesystems namens Spezifität (englisch: specificity). Und ja, das heißt tatsächlich so, und es ist nicht etwa bei der Übersetzung aus dem Englischen eine Silbe verloren gegangen.

Mittels Spezifität wird entschieden, welcher der unterschiedlichen Werte die höchste Relevanz hat. Zumindest die Grundbegriffe dieser Regeln sollten dem Web-Designer bekannt sein, wenn es nicht immer wieder zu Überraschungen kommen soll. Dieser Artikel setzt sich mit eben diesen Grundbegriffen auseinander.

 

Überraschung, Überraschung…

 

Eines der ersten Dinge, die man lernt, wenn man beginnt, sich mit CSS zu beschäftigen, ist, wie man Elemente ansprechen kann: mit den sogenannten Selektoren.

Wir lernen, dass es ID-, Klassen- und Typ-Selektoren gibt, und wer schon ein bisschen fortgeschrittener ist, weiß auch um Universal-, Attribut- und Pseudo-Selektoren.

Und dann kommt irgendwann der Moment, in dem irgendein Element nicht so will, wie es soll. Beispielsweise eine Schriftfarbe, die ganz und gar nicht so ausfällt, wie wir das eigentlich erwartet hätten.

Das liegt vermutlich daran, dass hier die Spezifität (specificity) gegriffen hat.

Die Spezifität bestimmt anhand eines Punktesystems, welche Selektoren schwerer wiegen und daher zum Tragen kommen, wenn ein Wert (oft unbeabsichtigt) über mehrere Selektoren(-ketten) angesprochen wird.

 

Eine kleine Auffrischung

 

Diese vereinfachte Tabellenübersicht gibt einen kurzen Überblick über die gängigsten Selektoren:

 

Beispiel

Selektor

Erklärung

p

Typselektor

Wählt alle <p>-Elemente aus.

th, td

Element und Element

Wählt alle <th>- und alle <td>-Elemente aus.

div p

Element in Element (Nachfahren-Kombinator)

Wählt alle <p>-Elemente aus, die sich in einem <div>-Element befinden.

*

Universalselektor

Wählt alles aus.

.content

Klassenselektor

Klassenselektor; wählt alle Elemente mit dieser Klasse (class="content“) aus.

#container

ID-Selektor

Wählt das Element mit der Id (id="container“) aus.

:hover

Pseudo-Klassen-Selektor

Wählt einen bestimmten Zustand aus (hier: mouseover).

::first-letter

Pseudo-Element-Selektor

Wählt einen bestimmten Teil eines Elements aus (hier: den ersten Buchstaben).

[a=“xyz“]

Attributselektor

Wählt ein bestimmtes Attribut (mit einem bestimmten Wert) aus

 

 

Das ist einfach genug – wenn man denn die Seite genau genug geplant hat und das CSS-Dokument kurz, knapp und übersichtlich ist. Leider entspricht das nicht immer der Praxis. Manche Seiten sind im Lauf der Zeit gewachsen, sind von anderen Developern übernommen worden, die alle ihren Teil hinzugefügt haben, und man hat mit Skript-Monstern zu tun, in denen es schwer ist, überhaupt etwas zu finden. Da kann es leicht vorkommen, dass ein Element von mehreren Deklarationen angesprochen wird. Genau dann wird Spezifität wichtig.

 

Verwirrte Browser: Welcher Wert soll verwendet werden?

 

Wenn nun demselben Attribut mehrere Werte zugewiesen werden, gibt es Regeln, welcher Wert dann vom Browser zur Darstellung verwendet wird.

Nehmen wir als einfaches Beispiel die Schriftfarbe. Wird ein Attribut doppelt belegt, wird der Eintrag, der zuletzt kommt, verwendet:




 

 


So einfach haben wir es aber leider selten. Unsere Selektoren sind verknüpft und verschachtelt, und es gibt Klassen und IDs…

Manchmal wird ein Element mit einer Klasse versehen, um ihm ein gesondertes Styling verpassen zu können – aber nichts passiert. Dann hat vermutlich die Spezifität zugeschlagen:



 

In diesem Beispiel wurde versucht, einen bestimmten Paragraphen innerhalb eines Divs grün zu schreiben. Die Schrift ist allerdings weiterhin rot – denn der erste Eintrag hat eine höhere Spezifität. (Siehe Codepen-Beispiel hier.)

 

Von der höchsten bis zur niedrigsten Spezifität

 

Während ein paar Regeln, welcher Wert denn nun verwendet werden soll, intuitiv verständlich und allgemein bekannt sind, ist das dahinterliegende Prinzip der Spezifität doch etwas komplexer.

Stark vereinfacht gesagt: Es werden Punkte vergeben, und die Regel mit der höchsten Punkteanzahl „gewinnt“.

Hier ein Kurzüberblick über die Gewichtung der Selektoren:


 



 

In vielen Fällen wird das ausreichen, um zu erklären, warum welcher Wert verwendet wurde, aber natürlich können und werden wir noch etwas in die Tiefe gehen.

Zur Erklärung der Übersicht:

Inline

Spezifischer, als ein Element im HMTL-Dokument inline mittels Style-Attribut anzusprechen, geht’s nicht mehr. Damit wird sichergestellt, dass tatsächlich genau dieses Element gemeint ist, und in der Spezifität bekommt es die „höchste Punkteanzahl“.

Trotzdem ist inline-CSS normalerweise keine gute Wahl. Abgesehen davon, dass damit vielleicht auch ungewollt Attributswerte aus dem Stylesheet überschrieben werden, bläht inline-CSS auch das HTML-Dokument unnötig auf, macht es unleserlich und für nachfolgende Developer schwer zu finden.

ID

Ein ID-Selektor bekommt die nächsthöhere Priorität. Da eine ID ein eindeutiger Identifikator eines Elements ist, wird damit ganz genau ein bestimmtes Element angesprochen. Somit ist die ID von allen Selektoren die spezifischste – daher auch die Bezeichnung Spezifität. Wird eine ID verwendet, ist die Spezifität auf jeden Fall höher, unabhängig davon, wieviele Klassen- oder Typselektoren sonst noch verwendet werden. Das erklärt auch, warum die Schrift im Beispiel oben rot, nicht grün war.

Class

Eine Klasse kann mehreren Elementen zugeordnet werden. Sie ist somit weniger spezifisch als eine ID; aber immer noch spezifischer, als eine ganze Elementen-Gruppe anzuwählen. Zu dieser Spezifität gehören außerdem noch Attributselektoren und Pseudo-Klassen.

Typ

Am wenigsten schwer wiegen ganze Element-Gruppen, also Typ-Selektoren. Wird beispielsweise „p“, als Selektor verwendet, gilt das zunächst für alle Paragraphen, ist also am wenigsten spezifisch. Auch Pseudo-Elemente zählen in diesem Fall zu dieser Gruppe.

 

Das Punktesystem der Spezifität

 

Wie also funktioniert nun das eigentliche Punktesystem?

Für jeden verwendeten Selektor wird ein Punkt in einer der obgenannten Kategorien vergeben. Man kann sich das so vorstellen:


 


Würde man beispielsweise einen Style für alle h1-Überschriften definieren, würde das folgendermaßen gezählt werden:


 


Die Spezifität für h1 wäre also 0,0,0,1.


Ein weiteres, realistisches, aber schon etwas kniffligeres Beispiel zur Spezifität:


 


Dieser Link, der sich in einer unordered list mit der ID „nav-bar“ und einem li-Element mit der Klasse „active“ befindet, hat die Spezifität 0,1,1,3. Somit kann ihm ein anderes Styling verliehen werden, als den anderen Links in dieser Navigationsleiste („ul#nav-bar li a“ hat nur eine Spezifität von 0,1,0,3).



 

Wird ein Wert im HTML-Dokument inline mittels Style-Attribut festgelegt, entspricht das der höchsten Spezifität. In diesem Beispiel 1,0,0,0.

 

Ausnahmen

 

·        Der oben in der tabellarischen Übersicht erwähnte Universalselektor (*) erhöht die Spezifität NICHT.

·        Die Pseudo-Klasse :not() erhöht die Spezifität ebenfalls nicht; das übergebene Argument allerdings schon.

Beispiel:

p:not(.myClass) hat eine Spezifität von 0,0,1,1.

·        !important überschreibt auch inline Style-Attribute. Allerdings sollte !important nur äußerst sparsam und wohlüberlegt (und idealerweise gar nicht) eingesetzt werden.

 

Links

 

Die W3C-Spezifikation zur specificity findet sich hier.

Andy Clarke beschreibt specificity in seinem Blog so:


 

 

 

 

 

Kommentare sind geschlossen