aslain.dev
0%
01 Hizmetler 02 Hakkımda 03 Projeler 04 Stack 05 Blog 06 İletişim
← Tüm makaleler Frontend & UI

CSS Specificity: Welche Regel gewinnt?

Du setzt aus drei verschiedenen Stellen eine Farbe auf ein Element, doch der Browser wählt ausgerechnet die, die du nicht wolltest. Genau hier kommt CSS Specificity ins Spiel: Sie ist das Prioritätssystem, das entscheidet, welche Regel gewinnt, wenn mehrere Deklarationen dasselbe Element ansprechen. Sobald du Specificity verstanden hast, verschwinden die Stunden, die du mit "Warum greift dieser Stil nicht?" verloren hast. Statt wahllos !important zu verteilen, siehst du genau, warum eine Regel wirkt oder nicht.

Was die Cascade ist und wo Specificity hineinpasst

Das "Cascading" in CSS ist der Prozess, mit dem der Browser widersprüchliche Regeln ordnet. Um einen Sieger zu bestimmen, durchläuft er diese Schritte der Reihe nach:

  • Herkunft und Wichtigkeit: woher der Stil kommt (Browser-Standards, Nutzerstile, Autorenstile) und ob er !important trägt.
  • Specificity: wie "spezifisch" der Selektor ist — unser Hauptfokus hier.
  • Quellreihenfolge: wenn alles andere gleich ist, gewinnt die zuletzt im Dokument geschriebene Regel.

Specificity entscheidet also nicht allein; sie ist eine Stufe der Cascade. Aber im Alltag ist sie die Stufe, die am meisten verwirrt und die meisten Konflikte verursacht.

Wie Specificity berechnet wird: ein dreiteiliger Wert

Stell dir vor, jeder Selektor erhält einen Wert mit drei Komponenten, oft als Tripel (a, b, c) geschrieben:

  • a — ID-Selektoren: jede ID wie #header zählt einen Punkt.
  • b — Klassen, Attribute und Pseudoklassen: jede .btn, [type="text"], :hover zählt einen Punkt.
  • c — Elemente und Pseudoelemente: jedes div, a, ::before zählt einen Punkt.

Der Vergleich läuft von links nach rechts: zuerst a, bei Gleichstand dann b, dann c. Ein paar Beispiele:

/* (0,0,1) — einzelnes Element */
p { color: black; }

/* (0,1,1) — eine Klasse + ein Element */
p.intro { color: blue; }

/* (1,0,0) — einzelne ID */
#main { color: green; }

/* (1,1,1) — ID + Klasse + Element */
#main p.intro { color: red; }

Zielen alle auf dasselbe <p class="intro">, gewinnt #main p.intro mit dem höchsten Wert, also ist die Farbe Rot. Ein entscheidendes Detail: Die Werte werden nicht zur Basis zehn addiert. Elf Klassen (0,11,0) schlagen niemals eine einzige ID (1,0,0). Eine einzige 1 in der a-Spalte übertrifft jede Menge Punkte in der b-Spalte.

Selektoren, die nichts zählen, und Sonderfälle

Manche Dinge tragen nichts zur Specificity bei:

  • Der Universalselektor * und die Kombinatoren (>, +, ~, Leerzeichen) fügen nichts hinzu.
  • :where() erzeugt immer null Specificity, egal was du hineinschreibst. Perfekt, um "weiche" Standards zu schreiben, die leicht zu überschreiben sind.
  • :is() und :not() fügen selbst nichts hinzu, übernehmen aber den Wert des spezifischsten Selektors darin. So zählt :is(#a, .b) genauso viel wie eine ID.
/* eine Regel mit :where() hat null Specificity */
:where(.card) a { color: teal; }

/* selbst ein einzelner Element-Selektor schlägt sie (0,0,2 > 0,0,1) */
.card a { color: orange; }

!important und Inline-Stile: die Reihenfolgebrecher

Zwei Dinge stehen außerhalb der normalen Specificity-Berechnung. Das erste sind Inline-Stile, das style-Attribut, das stärker ist als jede selektorbasierte Regel (konzeptuell eine vierte, ganz linke Spalte). Das zweite ist !important: Es einer Deklaration hinzuzufügen verschiebt diese in eine eigene, höhere Ebene.

<p id="x" style="color: green">Hallo</p>

#x { color: red; }              /* Inline gewinnt → grün */
#x { color: blue !important; }  /* !important schlägt sogar Inline → blau */

Wenn zwei !important-Deklarationen kollidieren, entscheiden wieder normale Specificity und Quellreihenfolge zwischen ihnen. Der praktische Rat ist klar: Behandle !important als letztes Mittel. Sobald du es benutzt, braucht das Überschreiben wieder ein !important, und dein Stylesheet wird zum Eskalationskrieg.

Specificity-Kriege in der Praxis vermeiden

Das Ziel ist, mit niedriger und konsistenter Specificity zu arbeiten:

  • Nutze Klassen statt IDs: Beim Stylen bringen IDs einen unnötig hohen Wert. Halte deine Selektoren klassenbasiert.
  • Halte Selektoren flach: statt .nav ul li a ziele direkt auf eine einzelne Klasse wie .nav-link.
  • Nutze Cascade Layers: mit @layer legst du die Ebenenpriorität explizit fest; eine spätere Ebene schlägt eine frühere, unabhängig von der Specificity.
  • Nutze :where() für weiche Standards, damit Nutzer einer Komponente Stile leicht überschreiben können.

Öffne das "Styles"-Panel in den DevTools deines Browsers: durchgestrichene Deklarationen zeigen sofort, welche Regel überschrieben wurde und welche gewonnen hat. Dieses Panel zu lesen statt zu raten ist der schnellste Weg, Specificity zu verinnerlichen.

Häufige Fragen

Was passiert bei gleicher Specificity?

Sind Herkunft, Wichtigkeit und Specificity alle gleich, entscheidet die Quellreihenfolge: Die zuletzt im CSS definierte Regel gewinnt. Deshalb genügt es oft, ein Override nach der bestehenden Regel zu platzieren.

Gewinnt !important immer?

Unter Autorenstilen schlägt es fast immer normale Deklarationen. Aber wenn eine andere !important-Deklaration eine höhere Specificity hat oder später kommt, gewinnt diese. Baue, wo möglich, eine Struktur, die gar kein !important braucht.

Was ist der Unterschied zwischen :is() und :where()?

Beide gruppieren eine Selektorliste und treffen dieselben Elemente. Der Unterschied liegt in der Specificity: :is() übernimmt den Wert des spezifischsten Selektors darin, während :where() immer null erzeugt.

Wenn deine Stilkonflikte gewachsen sind und dein CSS zu einem unhaltbaren Haufen von !important geworden ist, helfe ich dir, die Architektur auf eine klassenbasierte, geschichtete Struktur umzustellen. Um ein Projekt zu besprechen, nimm Kontakt mit mir auf.

Bu kategorideki tüm yazılar →

Devamı için