CSS-Kurs / CSS mit gemeinsamen Regeln, Nesting und Kaskaden-Layern organisieren

Wartbares CSS trennt gemeinsame Werte, Basisstile, Komponenten und bedingte Anpassungen nach ihren Rollen. Native Verschachtelung gruppiert verwandte Selektoren, während Kaskadenschichten Gruppen von Regeln explizit anordnen und eigene Prioritätsregeln einführen.

Duplikate reduzieren und Dateiverantwortlichkeiten zuweisen

Suchen Sie zunächst nach Duplikaten derselben Farbe und Abstände, veralteten Selektoren und fast identischen Button-Regeln. Werte mit derselben Rolle werden in Variablen gruppiert, und verschiedene Buttons teilen gemeinsame Regeln und notwendige Unterschiede. Es kann besser sein, zwei unabhängige Komponenten beizubehalten, anstatt komplexe Bedingungen zu erstellen, um alle Duplikate zu eliminieren. Beim Gruppieren gemeinsamer Werte überprüfen Sie den Geltungsbereich und die Vererbungsbedingungen der Variablen in CSS Variablen: var(), Geltungsbereich, Vererbung und Fallbacks.

/* Before cleanup: Same value repeated in multiple places */
.lesson-button { padding: .65rem 1rem; color: #166b92; }
.notice-button { padding: .65rem 1rem; color: #166b92; }

/* After organizing: sharing common shapes and roles */
.button { padding: .65rem 1rem; color: var(--accent); }
.button.text-alert { color: #9d2632; }

Der obige Vergleich ist ein Teilcode, der die Bereinigungsrichtung erklärt. Eine gemeinsame Button-Klasse muss auch den betreffenden HTML-Elementen zugewiesen werden, und wenn Sie nur das CSS umbenennen und das HTML unverändert lassen, kann das Aussehen verschwinden. Die gesamte Übung unten führt diese Konfiguration in Dateien und Schichten aufgeteilt aus.

Datei Verantwortung Urteil bei Überarbeitung
tokens.css Gemeinsame Farben und Abstände Ist es ein Wert, der von mehreren Komponenten geteilt wird?
base.css Schriftart, Standardabstand, Fokusanzeige Ist dies das Standardverhalten für das gesamte Dokument?
layout.css Inhaltsbereich und Layout Ist es die Positionsbeziehung der Komponenten?
components.css Form und Status von Karten und Schaltflächen Ist es mit einer Komponente verbunden?
utilities.css Kleine, explizite Hilfsklassen Ist dies eine Ausnahme, die nur an wenigen Stellen angewendet wird?

Für kleine Dokumente genügt oft eine einzige Datei, deren Abschnitte durch Kommentare gegliedert sind. Ziehen Sie in Betracht, Dateien zu trennen, wenn mehrere Personen verschiedene Komponenten ändern oder wenn der Wiederverwendungsbereich zunimmt. Der Dateiname dient als Trenner für die Navigation, und das bloße Teilen der Datei beseitigt keine Selektorkonflikte. HTML-Verbindungspfade und Kaskaden müssen ebenfalls verwaltet werden.

Unterscheiden Sie den Elternteil und die Nachkommen in der Verschachtelung.

Native CSS-Verschachtelung wird direkt vom Browser interpretiert. Dies unterscheidet sich von der Art und Weise, wie Präprozessoren wie Sass während der Build-Phase unterschiedliche CSS erzeugen. Der folgende Code platziert den Titel der .card nahe am Zustand der Karte selbst.

.card {
  & h2 { color: var(--accent); }
  &:hover { border-color: var(--accent); }
}

& h2 repräsentiert das h2 innerhalb der Karte, und &:hover repräsentiert das Hover der Karte selbst. Wenn Sie einen Abstand wie & :hover einfügen, wird das Ergebnis unterschiedlich sein, da es das mit der Maus berührte Nachkommelement auswählt. Unterscheiden Sie auch zwischen &.warning, das eine Hilfsklasse desselben Elements auswählt, und & .warning, das Nachkommen auswählt.

/* The simple overlap above is expanded */
.card h2 { color: var(--accent); }
.card:hover { border-color: var(--accent); }

Mit diesem einzelnen Elternselektor kann die Verschachtelung direkt mit den erweiterten Regeln verglichen werden. Eine durch Kommas getrennte Elternliste kann die Spezifität des verschachtelten Selektors von dem spezifischsten Selektor in dieser Liste abhängig machen. Komplexe Verschachtelungen sind daher keine einfache Zeichenkettenverkettung. Vermeiden Sie unnötige Verschachtelungstiefe, die CSS an eine starre HTML-Hierarchie binden. Für weitere Details siehe MDN Anleitung zur Nutzung von Verschachtelungen, Verschachtelung und Prioritätserklärung.

Prüfen Sie die Nesting-Unterstützung der benötigten Browser. Für ältere Umgebungen verwenden Sie die ausgeschriebenen Selektoren oder ein geeignetes Build-Werkzeug. Neue Syntax wird nicht automatisch von allen Zielbrowsern verstanden.

Vergleichen Sie Kaskaden-Layer vor der Spezifität

Bei regulären Deklarationen desselben Autorenstils haben Deklarationen außerhalb der Ebene Vorrang vor Deklarationen innerhalb der Ebene. Innerhalb von Ebenen haben spätere Ebenen Vorrang vor vorherigen Ebenen in einer vorgegebenen Reihenfolge. So können die Klassenregeln in der hinteren Ebene die ID-Regeln in der vorderen Ebene übertreffen. Wenn andere Vergleichsbedingungen wie dieselbe Ebene und Wichtigkeit gleich sind, werden anschließend Bedingungen wie CSS Vererbung, Spezifität und das Kaskadieren, Nähe der Abgrenzung und Deklarationsreihenfolge beurteilt.

@layer tokens, base, layout, components, utilities;
@layer base { #layer-target { color: #183044; } }
@layer utilities { .text-alert { color: #9d2632; } }

Die Beispiel-Schaltfläche stimmt mit beiden Selektoren überein. In der allgemeinen Deklaration folgt der Layer utilities später, daher gilt die Farbe Rot. Das Ergebnis nur deshalb vorherzusagen, weil eine Schaltfläche eine hohe ID-Priorität hat, kann falsch sein. Die Reihenfolge der Ebenen wird durch die Reihenfolge bestimmt, in der ihre Namen erstmals registriert werden, und selbst wenn Sie dieselbe Ebene später wieder öffnen, wird diese Ebene nicht nach hinten verschoben.

!important-Deklarationen haben Vorrang vor allgemeinen Deklarationen, und die Schichtenreihenfolge für wichtige Deklarationen ist umgekehrt. Wichtige Dinge in der vorderen Schicht haben Vorrang vor wichtigen Dingen in der hinteren Schicht, und wichtige Dinge innerhalb einer Schicht haben Vorrang vor wichtigen Dingen außerhalb der Schicht. Dieses Beispiel beschränkt sich darauf, Schichten von CSS desselben Autors und deren Eigenschaften zu vergleichen. Es erweitert sich nicht auf andere Bedingungen der Kaskade, wie Benutzer-/Browserstile, Inline-Deklarationen und laufende Übergänge, und sagt: „Sie müssen nur auf die Schichten schauen.“ Die vollständigen Bedingungen können im MDN-Schichtdokument nachgeprüft werden.

Erstellen Sie die HTML- und fünf CSS-Dateien

Erstellen Sie die untenstehende Struktur in einem leeren Ordner. Alle Dateien werden als UTF-8 gespeichert. Da index.html den relativen Pfad styles/... verwendet, muss die CSS-Datei im Unterordner styles liegen. Sie können index.html mit einem Browser öffnen, ohne einen separaten Server oder eine externe Bibliothek zu verwenden. Wenn Sie die Datei nicht lesen können, vergleichen Sie den Speicherort der Datei und die Verbindungsadresse mit CSS mit Inline-, internen und externen Styles anwenden.

stylesheet-project/
  index.html
  styles/
    tokens.css
    base.css
    layout.css
    components.css
    utilities.css

index.html enthält die tatsächlichen Link-Tags und Klassen. Der Vergleichsbutton ist kein Button, um eine Aktion auszuführen, sondern dient zu Übungszwecken, um die angewendete Textfarbe und den Fokus zu überprüfen.

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>CSS files and layers by responsibility</title>
  <link rel="stylesheet" href="styles/tokens.css">
  <link rel="stylesheet" href="styles/base.css">
  <link rel="stylesheet" href="styles/layout.css">
  <link rel="stylesheet" href="styles/components.css">
  <link rel="stylesheet" href="styles/utilities.css">
</head>
<body>
  <main class="demo">
    <h1>Organizing a small stylesheet</h1>
    <article class="card">
      <h2>Scope nested rules to the card</h2>
      <p>The card heading uses the accent color. Compare it with the heading outside the card.</p>
      <button class="button" type="button">Regular button</button>
    </article>
    <section><h2>Heading outside the card</h2><p>Use the default font color.</p></section>
    <button id="layer-target" class="button text-alert" type="button">Layer comparison button</button>
  </main>
</body>
</html>

styles/tokens.css registriert zuerst die Layer-Reihenfolge und deklariert gemeinsame Werte. Eine andere Datei öffnet einen Layer mit demselben Namen, um Regeln hinzuzufügen.

@layer tokens, base, layout, components, utilities;
@layer tokens {
  :root { --ink: #183044; --accent: #166b92; --space-card: 1.25rem; }
}

styles/base.css legt das Standarddokumentenlayout und den Fokusindikator fest. Die ID-Regel dient hier nur dazu, den Vorrang der Layer gegenüber der Spezifität zu vergleichen.

@layer base {
  *, *::before, *::after { box-sizing: border-box; }
  body { margin: 0; padding: 1rem; color: var(--ink); font-family: sans-serif; line-height: 1.6; }
  h1 { font-size: 1.5rem; } h2 { font-size: 1.2rem; }
  button { font: inherit; cursor: pointer; }
  :focus-visible { outline: 3px solid #164f73; outline-offset: 3px; }
  #layer-target { color: #183044; }
}

styles/layout.css verwaltet den Abstand zwischen Inhaltsbereichen und Abschnitten.

@layer layout {
  .demo { display: grid; gap: 1rem; max-width: 44rem; margin-inline: auto; }
  .demo > h1 { margin-block: 0 .5rem; }
  .demo > button { justify-self: start; }
}

styles/components.css verwaltet Karten und Schaltflächen. Die Titel-Farbe gilt nur für die Innenseite der Karte, und der Rand ändert sich, wenn man über die Karte fährt oder die Schaltfläche darin fokussiert.

@layer components {
  .card {
    padding: var(--space-card); border: 2px solid #90a4b2; border-radius: .5rem;
    & h2 { margin-top: 0; color: var(--accent); }
    &:hover, &:focus-within { border-color: var(--accent); }
  }
  .button {
    padding: .65rem 1rem; color: var(--accent); background: #eaf4fa;
    border: 1px solid #166b92; border-radius: .3rem;
  }
}

styles/utilities.css verwaltet eine Hilfsklasse für die Vergleichsschaltfläche. Allgemeine Deklarationen in dieser Datei haben Vorrang vor ID-/Button-Regeln in den vorherigen Ebenen.

@layer utilities {
  .text-alert { color: #9d2632; }
}

Prüfen Sie Dateien, Nesting und Layer unabhängig

  1. Auf dem Hauptbildschirm stellen Sie sicher, dass der Kartentitel und der allgemeine Button blau sind, der Titel außerhalb der Karte die Standardfarbe hat und der Vergleichsbutton rot ist. Navigieren Sie mit der Tabulatortaste, um zu sehen, ob der Button einen Fokusindikator hat.
  2. Kommentieren Sie nur die & h2-Regel innerhalb der Karte in components.css aus. Die Kartentitel kehren ebenfalls zu ihren Standardfarben zurück. Nach der Bestätigung wieder einkommentieren.
  3. Fügen Sie die Klasse text-alert beiden Buttons im HTML hinzu. Die Buttons innerhalb der Karte werden ebenfalls rot sein. Entfernen Sie anschließend text-alert wieder vom inneren Button.
  4. Am Ende von components.css ergänzen Sie nur .button { color: #28633b; } außerhalb des @layer-Blocks hinzu. Beide Schaltflächen werden grün. Dies führt dazu, dass allgemeine Deklarationen außerhalb der Ebene die Ebenenreihenfolge vorangestellt werden. Entfernen Sie die neue Regel nach dem Vergleich.
  5. Ergänzen Sie !important nur an der color-Deklaration der ID-Regel in base.css. Der Vergleichsbutton nimmt deren Grundfarbe an. Ergänzen Sie anschließend auch !important an color in utilities.css: Wegen der umgekehrten Layer-Reihenfolge bleibt die Grundfarbe aus base erhalten. Entfernen Sie danach beide !important-Zusätze.
  6. Entfernen Sie vorübergehend nur den Link zu components.css aus dem HTML. Die Komponentenformen der Karte und der Schaltfläche verschwinden. Stellen Sie die Verknüpfung wieder mit dem ursprünglichen Zustand und aktualisiere, um sie wiederherzustellen.

Prüfen Sie fehlende Styles

Überprüfen Sie separat auf Probleme mit der Dateitrennung und Konflikte von Selektoren. Sehen Sie sich zuerst im Bereich Netzwerk oder Quellen in den Entwicklertools Ihres Browsers an, ob die Datei tatsächlich geladen wurde, und wählen Sie dann das Element aus, um zu sehen, ob die Regeln in den Stilen übereinstimmen und ob Deklarationen überschrieben wurden. Wenn Sie die Datei nicht sehen, überprüfen Sie den relativen Pfad, den Dateinamen und die Erweiterung, und wenn Sie die Regel nicht sehen, überprüfen Sie die Klasse und die Unterstützung der Syntax.

Selbst wenn eine übereinstimmende Regel vorhanden ist, wird bei einem Durchstreichen Layer, !important, Spezifität, Gültigkeitsbereich und Reihenfolge verglichen. Wenn gemeinsame Variablen nicht wie erwartet sind, sollte auch der Bereich der Variablendeklaration überprüft werden. Nach der Trennung ist es hilfreich für die Wartung, den Hauptbildschirm sowie Fokus/Hover erneut zu prüfen und die Verantwortungsbereiche und Selektoren zu korrigieren, die Konflikte verursacht haben, anstatt weiterhin unnötige important-Deklarationen hinzuzufügen.