CSS Specificity Kaskade
CSS Spezifität und Kaskade
Verstehen Sie, warum manche CSS-Regeln andere überschreiben. Die Spezifität bestimmt, welche Regel bei Konflikten gewinnt.
Die Kaskade-Reihenfolge
Wenn mehrere Regeln auf ein Element zutreffen: 1. WICHTIGKEIT !important > normale Regeln 2. HERKUNFT Author Styles > User Styles > Browser Defaults 3. SPEZIFITÄT Höhere Spezifität gewinnt 4. QUELLREIHENFOLGE Spätere Regel gewinnt bei gleicher Spezifität
Spezifität berechnen
Spezifität wird als (A, B, C) berechnet: A = Anzahl ID-Selektoren (#id) B = Anzahl Klassen, Attribute, Pseudo-Klassen (.class, [attr], :hover) C = Anzahl Element-Selektoren, Pseudo-Elemente (div, ::before) * (Universal) und Kombinatoren (+, >, ~) zählen nicht!
| Selektor | Spezifität |
|---|---|
* |
(0, 0, 0) |
div |
(0, 0, 1) |
div p |
(0, 0, 2) |
.class |
(0, 1, 0) |
div.class |
(0, 1, 1) |
.class1.class2 |
(0, 2, 0) |
#id |
(1, 0, 0) |
#id .class |
(1, 1, 0) |
#id .class div |
(1, 1, 1) |
style="" (inline) |
(1, 0, 0, 0) - eigene Ebene! |
Praktische Beispiele
/* Welche Farbe hat der Text? */
/* (0, 1, 0) */
.button {
color: blue;
}
/* (0, 1, 1) - GEWINNT */
p.button {
color: red;
}
/* (0, 0, 1) */
p {
color: green;
}
/* Ergebnis: red (höchste Spezifität) */
/* Komplexeres Beispiel */
/* (0, 2, 1) */
nav .menu .item {
color: blue;
}
/* (0, 1, 3) */
header nav ul li {
color: red;
}
/* (0, 2, 1) vs (0, 1, 3)
2 > 1 bei den Klassen
→ Blau gewinnt! */
Pseudo-Klassen und Pseudo-Elemente
/* Pseudo-Klassen zählen als Klasse (0, 1, 0) */
a:hover { } /* (0, 1, 1) */
.link:hover { } /* (0, 2, 0) */
.link:first-child { } /* (0, 2, 0) */
/* Pseudo-Elemente zählen als Element (0, 0, 1) */
p::first-line { } /* (0, 0, 2) */
.text::before { } /* (0, 1, 1) */
/* Ausnahmen: :is(), :where(), :not() */
:is(h1, h2, h3) { } /* Höchste Spezifität der Argumente */
:where(h1, h2, h3) { } /* Immer (0, 0, 0)! */
:not(.class) { } /* Spezifität des Arguments */
/* Beispiel mit :is() */
:is(.header, #nav) .link { }
/* Die Spezifität ist (1, 1, 0) wegen #nav */
/* Beispiel mit :where() */
:where(.header, #nav) .link { }
/* Die Spezifität ist nur (0, 1, 0) */
!important - Der Notausgang
/* !important überschreibt ALLES (außer andere !important) */
.button {
color: blue !important;
}
#special.button {
color: red; /* Verliert trotz höherer Spezifität! */
}
/* !important-Konflikte: Spezifität zählt wieder */
.button {
color: blue !important; /* (0, 1, 0) + important */
}
#special {
color: red !important; /* (1, 0, 0) + important → GEWINNT */
}
/* ⚠️ !important vermeiden! */
/* Legitime Anwendungsfälle: */
/* - Utility-Klassen: .hidden { display: none !important; } */
/* - Third-Party-CSS überschreiben */
/* - Print-Styles */
Inline Styles
/* Inline Styles haben eigene Ebene */
<div style="color: red;">Text</div>
/* Diese Regel verliert: */
#super-specific.many.classes div {
color: blue; /* Inline gewinnt! */
}
/* Nur !important kann Inline überschreiben: */
div {
color: blue !important;
}
Best Practices
/* ✅ Flache Spezifität bevorzugen */
.card { }
.card-title { }
.card-content { }
/* ❌ Zu spezifisch */
.page .main-content .card-list .card .card-title { }
/* ✅ BEM-Methodik */
.card { }
.card__title { }
.card__content { }
.card--highlighted { }
/* ✅ Utility-Klassen mit niedriger Spezifität */
.text-center { text-align: center; }
.mt-4 { margin-top: 1rem; }
/* ✅ :where() für resettbare Defaults */
:where(.button) {
padding: 10px 20px;
border-radius: 4px;
}
/* Leicht überschreibbar: */
.my-button {
padding: 5px 10px; /* Gewinnt! */
}
Spezifitätskrieg vermeiden
/* ❌ Problem: Eskalation */
.button { color: blue; }
.sidebar .button { color: red; }
.sidebar .content .button { color: green; }
#sidebar .content .button { color: yellow; }
#sidebar .content .button.active { color: purple; }
/* ... !important kommt als nächstes ... */
/* ✅ Lösung: Modifizierer-Klassen */
.button { color: blue; }
.button--sidebar { color: red; }
.button--active { color: purple; }
/* ✅ Lösung: CSS Layers (Modern) */
@layer base, components, utilities;
@layer base {
a { color: blue; }
}
@layer components {
.link { color: inherit; } /* Gewinnt wegen Layer-Order */
}
@layer utilities {
.text-red { color: red !important; }
}
CSS Layers (@layer)
/* Moderne Lösung für Spezifitätskontrolle */
/* Layer-Reihenfolge definieren */
@layer reset, base, components, utilities;
/* Spätere Layer überschreiben frühere */
/* Unabhängig von der Spezifität! */
@layer reset {
* { margin: 0; padding: 0; }
}
@layer base {
a { color: blue; }
}
@layer components {
/* Überschreibt reset und base */
.button {
padding: 10px; /* Überschreibt reset */
}
}
@layer utilities {
/* Überschreibt alles */
.p-0 { padding: 0; }
}
/* Unlayered CSS hat höchste Priorität */
.special { } /* Über allen Layers */
Debugging-Tipps
/* DevTools zeigen Spezifität */
/* Chrome: Elements → Styles → Hover über Selektor */
/* Alle angewandten Styles sehen */
/* Chrome: Elements → Computed → "Show all" aktivieren */
/* Test: Temporär Spezifität erhöhen */
.debug.debug.debug.debug {
color: red; /* (0, 4, 0) für Debugging */
}
💡 Goldene Regel:
Halten Sie die Spezifität so niedrig wie möglich. Nutzen Sie Klassen statt IDs, flache Selektoren statt tief verschachtelter, und vermeiden Sie !important. Bei komplexen Projekten helfen CSS Layers oder BEM-Methodik.