Kaskade, Spezifität und Vererbung
Bisher hatte jedes Element höchstens eine passende Regel. In einem echten Stylesheet gelten für dasselbe Element oft mehrere. Dieses Kapitel klärt, wie der Browser dann entscheidet. Wer das versteht, muss bei CSS nicht mehr raten.
Was du am Ende kannst
Abschnitt betitelt „Was du am Ende kannst“- erkennen, wann zwei Regeln in Konflikt stehen und wann nicht
- bei gleich genauen Selektoren vorhersagen, welche Regel gewinnt
- die Spezifität eines Selektors bestimmen und vergleichen
- erklären, welche Eigenschaften vererbt werden
- begründen, warum
!importantselten die richtige Lösung ist
Live-Coding zum Mitmachen
⤓ demo-07-kaskade.zip herunterladenDer Ordner starter ist der Ausgangsstand, fertig der Stand nach dem Live-Coding.
Enthält: bilder/laufstrecke.svg, fest.html, index.html, kontakt.html, stil.css, termine.html
Das Problem: Zwei Regeln, ein Element
Abschnitt betitelt „Das Problem: Zwei Regeln, ein Element“Für jede Eigenschaft eines Elements kann am Ende nur ein Wert gelten. Sagen zwei Regeln Verschiedenes, muss der Browser sich entscheiden. Das ist kein Fehler, sondern der Normalfall in CSS.
Wichtig ist: Der Konflikt betrifft immer nur einzelne Eigenschaften, nicht ganze Regeln.
p { color: gray; font-style: italic;}
.hinweis { color: teal;}<p>Ein gewöhnlicher Absatz: grau und kursiv.</p><p class="hinweis">Die Farbe ist umstritten und wird türkis. Die Kursivschrift ist unumstritten und bleibt.</p>Beide Regeln treffen den zweiten Absatz. .hinweis setzt sich bei der Farbe durch. Die Kursivschrift kommt weiterhin aus der
Regel für p, denn dazu sagt .hinweis nichts. Die Regel für p hat also nicht verloren, sondern nur bei
einer Eigenschaft.
Warum aber gewinnt .hinweis? Dafür gibt es eine feste Rangfolge. Das Wort Cascading in CSS beschreibt genau
diesen Ablauf. Wir sehen uns die Kriterien vom einfachsten zum anspruchsvollsten an.
Erstes Kriterium: Die Reihenfolge
Abschnitt betitelt „Erstes Kriterium: Die Reihenfolge“Bei zwei gleich genauen Selektoren gewinnt die Regel, die später steht.
.hinweis { color: teal;}
.hinweis { color: purple;}<p class="hinweis">Beide Selektoren sind gleich genau. Die spätere Regel gewinnt: lila.</p>Das gilt auch über mehrere Dateien hinweg: Was später eingebunden wird, steht später. Ein allgemeines Stylesheet bindet man deshalb vor einem besonderen ein.
Zweites Kriterium: Die Spezifität
Abschnitt betitelt „Zweites Kriterium: Die Spezifität“Die Reihenfolge entscheidet nur bei gleich genauen Selektoren. Vorher zählt, wie genau ein Selektor ist. Diesen Wert nennt man Spezifität.
p.hinweis { color: teal;}
.hinweis { color: purple;}<p class="hinweis">p.hinweis ist genauer als .hinweis und gewinnt, obwohl die Regel früher steht: türkis.</p>Spezifität berechnen
Abschnitt betitelt „Spezifität berechnen“Du zählst drei Dinge im Selektor und schreibst sie als drei Zahlen:
| Stelle | Was gezählt wird |
|---|---|
| 1. Stelle | IDs |
| 2. Stelle | Klassen, Attribute und Pseudoklassen |
| 3. Stelle | Elemente und Pseudoelemente |
Ein paar Beispiele, Zeile für Zeile:
| Selektor | IDs | Klassen usw. | Elemente | Spezifität |
|---|---|---|---|---|
p |
0 | 0 | 1 | 0,0,1 |
nav a |
0 | 0 | 2 | 0,0,2 |
.hinweis |
0 | 1 | 0 | 0,1,0 |
p.hinweis |
0 | 1 | 1 | 0,1,1 |
a:hover |
0 | 1 | 1 | 0,1,1 |
[type="email"] |
0 | 1 | 0 | 0,1,0 |
#inhalt |
1 | 0 | 0 | 1,0,0 |
Spezifität vergleichen
Abschnitt betitelt „Spezifität vergleichen“Du vergleichst von links nach rechts. Die erste Stelle, die sich unterscheidet, entscheidet.
.hinweis(0,1,0) schlägtnav ul li a(0,0,4). Eine Klasse wiegt mehr als beliebig viele Elemente.#inhalt(1,0,0) schlägt.a .b .c(0,3,0). Eine ID wiegt mehr als beliebig viele Klassen.a:hoverundp.hinweissind gleich (0,1,1). Dann entscheidet wieder die Reihenfolge.
Damit erklärt sich auch der Rat aus dem letzten Kapitel, IDs im CSS zu meiden: Eine einmal mit ID geschriebene Regel lässt sich nur
schwer überschreiben. Der universelle Selektor * zählt gar nicht.
Ein style-Attribut am Element schlägt jeden Selektor.
In den DevTools nachsehen
Abschnitt betitelt „In den DevTools nachsehen“Im Styles-Bereich stehen die wirksamsten Regeln oben, und unterlegene Deklarationen sind durchgestrichen. Fährst du mit der Maus über einen Selektor, zeigt der Browser dessen Spezifität an. Das ist der schnellste Weg, einen Konflikt zu verstehen.
Die Rangfolge im Überblick
Abschnitt betitelt „Die Rangfolge im Überblick“Jetzt lässt sich der ganze Ablauf zusammensetzen. Der Browser prüft der Reihe nach, bis nur noch ein Wert übrig ist:
- Herkunft: Dein Stylesheet schlägt das Standard-Stylesheet des Browsers. Darum kannst du es überschreiben.
- Spezifität: Der genauere Selektor gewinnt.
- Reihenfolge: Bei Gleichstand gewinnt die spätere Regel.
Zwei Sonderfälle ergänzen diesen Ablauf, !important und Ebenen. Beide folgen am Ende des Kapitels.
Vererbung: Wenn gar keine Regel passt
Abschnitt betitelt „Vererbung: Wenn gar keine Regel passt“Die Rangfolge klärt, was bei mehreren passenden Regeln geschieht. Was aber, wenn für eine Eigenschaft keine Regel das Element trifft? Dann wird manche Eigenschaft vom Elternelement übernommen. Das heißt Vererbung.
So kannst du die Schrift einmal am body setzen, und sie gilt für die ganze Seite.
.karte { color: #0f766e; font-family: Georgia, serif; border: 2px solid #0f766e; padding: 0.5rem;}<div class="karte"> <p>Farbe und Schrift erbt dieser Absatz. Rahmen und Abstand erbt er nicht.</p> <button>Formularelemente erben die Schrift nicht von selbst</button></div>| Vererbt werden vor allem | Nicht vererbt werden vor allem |
|---|---|
Texteigenschaften: color, font-family, font-size, font-weight, line-height, text-align |
Eigenschaften der Box: margin, padding, border, width, background |
Das ist sinnvoll: Text soll einheitlich sein, aber nicht jedes Kind soll einen eigenen Rahmen bekommen.
Eine direkte Regel schlägt immer die Vererbung, ganz gleich wie spezifisch die Regel am Elternelement ist. Der vererbte Wert ist nur der Rückfall.
Formularelemente wie button und input erben die Schrift nicht von selbst. Mit dem Wert inherit holst du das
nach: font: inherit.
Sonderfall: !important
Abschnitt betitelt „Sonderfall: !important“!important hebt eine Deklaration über alle normalen Regeln:
.warnung { color: red !important;}Das löst ein Problem nur scheinbar: Beim nächsten Konflikt braucht es wieder ein !important, und das Stylesheet wird immer
schwerer zu ändern. Besser sind diese beiden Gewohnheiten:
- Selektoren kurz und flach halten, meist genügt eine Klasse.
- Eine zu spezifische Regel reparieren, statt sie zu überbieten.
Ausblick: @layer
Abschnitt betitelt „Ausblick: @layer“Ebenen geben dir eine feste Rangfolge, die sogar über der Spezifität steht:
@layer basis, komponenten;@layer komponenten { p { color: green; }}@layer basis { #sehr.spezifisch p { color: red; }}<div id="sehr" class="spezifisch"> <p>Grün: Die spätere Ebene gewinnt, egal wie spezifisch die frühere ist.</p></div>Das ist vor allem nützlich, wenn du ein fremdes Stylesheet einbindest: Es kommt in eine frühe Ebene, und dein eigenes CSS gewinnt ohne Wettlauf um die Spezifität. Regeln außerhalb jeder Ebene gewinnen gegen alle Ebenen. Für kleine Projekte brauchst du das noch nicht.
Live-Coding: Zwei Konflikte lösen
Abschnitt betitelt „Live-Coding: Zwei Konflikte lösen“Im Starter stehen am Ende von stil.css zwei Probleme: Der Menülink wird nicht türkis, und der Hinweis auf der
Kontaktseite wird nicht rot.
/* Neu: Warum wird der Menülink nicht türkis? */header nav .hauptmenue li a { color: #55606e;}
.hauptmenue a { color: #0f766e;}
/* Warum ist der Hinweis auf der Kontaktseite nicht rot? */main p.hinweis { color: #55606e;}
.warnung { color: #b91c1c;}Wir gehen so vor:
- Das Element in den DevTools untersuchen und die durchgestrichene Regel finden.
- Die Spezifität beider Regeln bestimmen und vergleichen.
- Die überspezifische Regel entfernen, statt ein
!importantzu ergänzen.
Starter für die Übung
⤓ uebung-07-kaskade.zip herunterladenZIP-Datei entpacken und den Ordner in VS Code öffnen (Datei → Ordner öffnen).
Enthält: bilder/laufstrecke.svg, fest.html, index.html, kontakt.html, raetsel.css, raetsel.html, stil.css, termine.html
Öffne raetsel.html noch nicht im Browser. Lies zuerst raetsel.css.
Stufe 1: Vorhersagen
Abschnitt betitelt „Stufe 1: Vorhersagen“Schreibe zu jedem Absatz auf, welche Farbe er bekommt und warum.
Stufe 2: Prüfen
Abschnitt betitelt „Stufe 2: Prüfen“Öffne die Seite und vergleiche. Wenn deine Vorhersage falsch war, finde im Styles-Bereich die gewinnende und die durchgestrichenen Regeln und vergleiche deren Spezifität.
Stufe 3: Ändern
Abschnitt betitelt „Stufe 3: Ändern“Absatz 5 soll die Farbe von .sechs bekommen. Schaffe das mit einer neuen Regel, ohne
!important und ohne die Regel p zu ändern.
Für Schnelle
Abschnitt betitelt „Für Schnelle“Ergänze zwei Ebenen basis und thema. In thema setzt du .eins auf Gold, in
basis setzt du #besonders auf Schwarz. Warum ändert sich bei beiden Absätzen nichts?