CSS-Kurs / Vererbung, Spezifität und Kaskade

Die Kaskade entscheidet zwischen konkurrierenden CSS-Deklarationen, während die Spezifität die Stärke von Selektoren innerhalb der relevanten Kaskadenbedingungen vergleicht. Die Vererbung liefert bestimmte Werte von einem Elternteil, wenn keine zutreffende Deklaration diese bestimmt; dies sind verwandte, aber unterschiedliche Mechanismen.

Unterscheiden Sie Vererbung von direkten Deklarationen

Vererbung bedeutet, dass ein Kindelement den Wert seines Elternelements übernimmt. Während Textfarbe und schriftbezogene Eigenschaften im Allgemeinen vererbt werden, werden Rand und Innenabstand standardmäßig nicht vererbt. Wenn Sie davon ausgehen, dass alle Eigenschaften gleich wie bei ihrem Elternelement sind, könnten Sie unerwartete Ränder in Ihren Absätzen feststellen.

#main {
  color: purple;
  border: 1px solid purple;
}
p { color: #555; }
<main id="main">
  <h1>Small Garden</h1>
  <p>Visitor information.</p>
</main>

Wenn wir davon ausgehen, dass wir nur diese beiden Teile anwenden, wird h1 die lila Farbe von seinem Elternelement main erben. Die graue Farbe, die Sie angeben, wird auf p angewendet. Nur weil der #main des Elternteils ein ID-Selektor ist, übertrumpft er nicht die direkte Zuweisung des Kinds p. Dies liegt daran, dass es kein Wettbewerb zwischen zwei Selektoren ist, die auf dasselbe Element angewendet werden. Der Rand wird um das Box-Element von main erstellt und wird nicht durch die Ränder von h1 beziehungsweise p dupliziert.

Nicht geerbte Eigenschaften können auch den berechneten Wert des Elternteils erben, indem sie ihn als border: inherit angeben. Umgekehrt wird eine Deklaration, die auf das Element zutrifft, auch wenn es sich um eine geerbte Eigenschaft handelt, zuerst verarbeitet. Sie können herausfinden, welche Eigenschaften vererbt werden und was Vererbung bedeutet, in der CSS-Vererbbeschreibung von MDN.

Befolgen Sie den Entscheidungsprozess der Kaskade

Beginnen Sie mit dem normalen CSS des Autors, wie zum Beispiel den Regeln, die Sie für diese Seite schreiben. Überprüfen Sie vor dem Vergleichen von Deklarationen, ob der Selektor übereinstimmt, die Syntax gültig ist und Bedingungen wie Media Queries zutreffen. Schließen Sie nicht übereinstimmende Regeln und ungültige Deklarationen vom Vergleich aus.

  1. Überprüfen Sie die Top-Bedingungen wie Quelle, Wichtigkeit und Ebene. Autor-CSS- und Benutzer-CSS-/Browser-Standardstilquellen, ob !important verwendet wird, ob @layer verwendet wird usw. sind hier relevant. Wenn die Top-Bedingungen unterschiedlich sind, wird die Entscheidung nicht allein durch den Vergleich der Selektorenwerte getroffen.
  2. Vergleichen Sie die Spezifität von Selektoren innerhalb derselben Bedingungen. Priorität (Spezifizität) ist ein Kriterium, um zu vergleichen, wie spezifisch ein Selektor ist. Vergleichen Sie ID, Klassenfamilie und Elementefamilie in dieser Reihenfolge.
  3. Wenn die Priorität gleich ist, wird die später geschriebene Deklaration verwendet. In Situationen, in denen es keine zusätzlichen Bedingungen wie @scope gibt, wie in den Beispielen dieser Lektion, werden endgültige Gleichstände in der Quellreihenfolge gelöst.
  4. Für jede Eigenschaft ermittelt CSS die zutreffenden Deklarationen und führt dann gegebenenfalls gegebenenfalls die Zuweisung von Standardwerten durch. Vererbbare Eigenschaften können einen Wert von der übergeordneten Ebene erhalten; andere Eigenschaften verwenden normalerweise ihren Initialwert. Dies bedeutet nicht, dass jede Deklaration in einer siegreichen Regel eine gesamte frühere Regel ersetzt.

Die Kaskade ist der vollständige Prozess der CSS-Konfliktlösung; die Spezifität von Selektoren ist ein Kriterium darin. Animationen, Übergänge, Layer und Bereiche führen weitere Regeln ein, sodass die einfachen Beispiele hier nicht jeden Fall darstellen. Die W3C-Kaskaden-Sortierregeln definieren die Beziehungen zwischen Ursprung, Wichtigkeit und Layern. Das vollständige Beispiel unten verwendet keine Animationen, Übergänge, @layer oder @scope. Die Organisation von CSS mit gemeinsamen Stilen, Verschachtelung und Layern zeigt, wie Regeln in Layer gruppiert werden.

Vergleichen Sie die Spezifität in drei Spalten

Der grundlegende Selektor in dieser Lektion kann in drei Spalten gelesen werden: Anzahl der IDs, Anzahl der Klassen/Attribute/Pseudo-Klassen und Anzahl der Elemente/Pseudo-Elemente. Vergleichen Sie die Spalten von links nach rechts. Der erste Unterschied entscheidet. Behandeln Sie die Werte nicht als Dezimalpunktzahl mit ID=100, Klasse=10 und Element=1: Viele Klassen erzeugen keinen Übertrag in die ID-Spalte. Nur weil es viele Klassen gibt, bedeutet das nicht, dass es über die ID-Spalte hinausgeht.

Selektor ID Klasse, Attribut, Pseudo-Klasse Element/Pseudo-Element Notation
p 0 0 1 0-0-1
.notice 0 1 0 0-1-0
p.notice 0 1 1 0-1-1
[required] 0 1 0 0-1-0
a:hover 0 1 1 0-1-1
p::before 0 0 2 0-0-2
#opening 1 0 0 1-0-0
#main .notice 1 1 0 1-1-0

p.notice und .notice haben die gleiche ID-Spalte und die gleiche Klassen-Spalte. Es gibt einen Unterschied zwischen 1 und 0 in der Elemente-Spalte, daher hat p.notice die höhere Spezifität. #opening und p.notice haben einen Unterschied von 1 und 0 in der ersten Spalte, daher hat #opening die höhere Spezifität. Leerzeichen, relationale Notationen wie >, +, ~ und der universelle Selektor * erhöhen nicht direkt die Anzahl dieser Vergleiche.

p.notice { color: #087f5b; }
.notice { color: tomato; }

Unter denselben Bedingungen von Ursprung, Wichtigkeit und Ebene hat p.notice eine höhere Spezifität als .notice, sodass seine grüne Farbe gewinnt, selbst wenn sie früher erscheint. Identische Selektoren haben die gleiche Spezifität, wodurch die Quellreihenfolge ein Unentschieden löst. Einige funktionale Pseudo-Klassen haben zusätzliche Spezifitätsregeln. Siehe MDN: Spezifität.

Ermitteln Sie den Wert jeder Eigenschaft getrennt

.notice {
  color: blue;
  padding: 12px;
  border: 1px solid #087f5b;
}
.notice {
  color: tomato;
  padding: 20px;
}

Wenn nur diese beiden Regeln auf dasselbe Element angewendet werden, verwenden Farbe und Padding die Deklaration aus der letzteren Regel, und der Rahmen der vorherigen Regel bleibt bestehen. Nur weil in der folgenden Regel kein Rahmen enthalten ist, bedeutet dies nicht, dass die gesamte vorherige Regel verschwindet. CSS sollte als „Bestimmung von Werten für jede Eigenschaft“ und nicht als „Auswahl eines gesamten Regelblocks“ verstanden werden.

Zum Beispiel kann die Textfarbe von einer ID-Regel stammen, der Außenabstand kann von einer späteren Klassenregel stammen, und die Rahmenlinie kann von einer vorherigen Klassenregel stammen. Selbst wenn Sie den Durchstreichungseffekt in den Entwickler-Tools sehen, lesen Sie die Deklarationen einzeln durch. Nur weil die Farbe durchgestrichen ist, bedeutet das nicht, dass das Padding desselben Blocks nicht angewendet wird.

Sagen Sie das Ergebnis des vollständigen Beispiels voraus

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Small Garden</title>
  <style>
body { margin: 24px; font-family: sans-serif; line-height: 1.7; }
    #main { color: purple; }
    p { color: #555; }
    .notice {
      color: blue;
      padding: 12px;
      border: 1px solid #087f5b;
    }
    p.notice { color: #087f5b; }
    .notice { color: tomato; padding: 20px; }
    #opening { color: #1d4ed8; }
  </style>
</head>
<body>
<main id="main">
    <h1>Small Garden</h1>
    <p id="opening" class="notice">A: We open at 9am every day.</p>
    <p class="notice">B: Prepare a water bottle and comfortable shoes.</p>
    <p>C: Please inquire at the information desk.</p>
  </main>
</body>
</html>

Sagen Sie die Farben von A·B·C und den Innenabstand der Hinweise voraus, bevor Sie es in Ihrem Browser öffnen. Wenn Sie den gesamten Code als index.html speichern und öffnen, erhalten Sie folgendes Ergebnis. Die Schriftart und Zeilenhöhe des Bodys sind Hilfseinstellungen für eine einfachere Ansicht.

Objekt und Eigenschaften Endergebnis Grund für die Entscheidung
Farbe von h1 Lila Erbt die Farbe von main. Es gibt keine anderen Farbangaben in h1.
Farbe von A Blau #1d4ed8 #opening hat eine höhere Spezifität als p.notice, .notice, p, die auf dasselbe A angewendet werden.
Farbe von B Grün #087f5b p.notice hat eine höhere Spezifität als die spätere Regel .notice.
Farbe von C Grau #555 Es verwendet einen direkten Wert für p und erbt nicht die lila Farbe des übergeordneten Elements.
Padding von A·B 20px Die beiden .notice-Deklarationen haben die gleiche Spezifität, daher setzt sich das spätere Padding durch.
Rahmen von A·B 1px grüne durchgezogene Linie Da es in der späteren Regel keine Rand-Deklaration gibt, bleibt die vorherige gültige Deklaration bestehen.

Wenn in Computed überprüft, kann die Farbe von A als rgb(29, 78, 216), die Farbe von B als rgb(8, 127, 91) und die Farbe von C als rgb(85, 85, 85) angezeigt werden. Auch wenn die Farbschreibweise unterschiedlich ist, bedeutet dies denselben Wert. Prüfen Sie, dass das Padding in jede Richtung 20px beträgt und dass Dicke und Linie des Rands gleich sind.

Vergleichen Sie !important und Inline-Stile

!important ist eine Kennzeichnung, die die Wichtigkeit einer Deklaration ändert. Es ist keine Funktion, die eine große Zahl zu den drei Spalten des Selektors hinzufügt. Aus derselben Quelle des Autors haben wichtige Deklarationen Vorrang vor normalen Deklarationen, sodass das Hinzufügen der folgenden Regel am Ende des gesamten Beispiels die Farbe von sowohl A als auch B auf die CSS-Farbe tomato ändert. Die einfache Farbangabe im ID hat ebenfalls keinen Vorrang vor dieser wichtigen Deklaration.

.notice { color: tomato !important; }

Dieses Ergebnis bedeutet nicht, dass !important immer stärker ist als alle Stile. Benutzerdefinierte wichtige Stile, Werte während Übergängen usw. folgen einer separaten Reihenfolge. Selbst bei wichtigen Anweisungen müssen Sie zuerst die Quelle und die Ebene überprüfen. In dieser Übung beobachten Sie zuerst !important und löschen dann die Regel, die Sie hinzugefügt haben. Normalerweise ist es für die Wartung besser, zuerst den Auswahlbereich und die Struktur zu organisieren.

<p class="notice" style="color: purple;">B: Information on what to prepare</p>

Im ursprünglichen Beispiel, in dem die wichtige Regel gelöscht wurde, gilt: Wenn Sie eine Inline-Farbe in B wie oben setzen, hat diese Vorrang vor den regulären Stylesheet-Regeln und B wird lila. Inline-Stile werden getrennt von den drei Standard-Selektorspalten in der obigen Tabelle behandelt. Wie bereits erwähnt, ermöglicht das Setzen von !important in der allgemeinen Klassenregel, dass sie Vorrang vor der regulären Inline-Farbe hat. Daher ist „wenn es inline ist, ist es bedingungslos das Stärkste“ ebenfalls eine Erklärung ohne Bedingungen.

Übung: Konflikte diagnostizieren

  1. Im ursprünglichen vollständigen Beispiel verschieben Sie die p.notice-Regel nach unten. Stellen Sie sicher, dass B weiterhin grün ist und A die blaue Farbe seiner ID behält. In Zuständen mit hoher Spezifität werden sie nicht einfach durch Ändern ihrer Reihenfolge überschrieben.
  2. Als Nächstes ändern Sie nur den p.notice-Selektor in .notice und platzieren ihn unten. Die Farbe von B verwendet das Grün, das durch das letzte .notice angegeben ist. Da wir denselben Selektor haben, ist jetzt die Reihenfolge das Entscheidungskriterium. Nach der Bestätigung stellen Sie das Original wieder her.
  3. Entfernen Sie id="opening" nur von A. Überprüfen Sie, ob A dasselbe Grün wie B annimmt. Auch wenn die ID des übergeordneten main gleich bleibt, übertrifft sie nicht die direkt A zugewiesene grüne Farbe. Stellen Sie danach die ID von A wieder her.
  4. In getrennten Schritten wenden Sie die oben genannten wichtigen und Inline-Beispiele nacheinander an und vergleichen sie. Stellen Sie vor jedem neuen Vergleich den Originalzustand wieder her und ändern Sie jeweils nur eine Bedingung.

Wenn das Ergebnis von Ihren Erwartungen abweicht, CSS mit DevTools prüfen: Styles und Computed. Wählen Sie das richtige Element aus, suchen Sie nach Deklarationen für die Eigenschaft, vergleichen Sie deren Wichtigkeit, Selektoren und Reihenfolge und prüfen Sie dann den endgültigen Wert. Das Hinzufügen von IDs oder !important ohne die Ursache zu finden, kann die Farbe jetzt ändern, macht spätere Bearbeitungen jedoch schwieriger.