Kodokon kodokon.com

CSS-Architektur: BEM, Utility-First, Dateiorganisation

Vergleiche BEM und den Utility-First-Ansatz, ihre echten Kompromisse im Team, und strukturiere deine Dateien mit Cascade Layers.

11 Min. · 3 Fragen

Diese Lektion in Kodokon öffnen

CSS zerbricht nicht auf der Ebene einer Komponente, sondern auf der Ebene eines Projekts: Spezifität, die nur steigt, um gegen eine bestehende Regel zu „gewinnen“, die Angst, Code zu löschen, dessen Reichweite du nicht kennst, Stile, die von einem Screen zum anderen überschwappen. Eine CSS-Architektur ist vor allem eine Strategie zur Verwaltung von Spezifität und Geltungsbereich. Die beiden dominierenden Schulen, BEM und Utility-First, beantworten dasselbe Problem auf entgegengesetzten Wegen.

BEM (Block, Element, Modifier) benennt jeden gestalteten Knoten: .card (ein eigenständiger Block), .card__title (ein Element, das zum Block gehört), .card--featured (eine Variante des Blocks). Die Konvention garantiert eine flache Spezifität - überall eine einzige Klasse, nie ein Nachfahrenselektor -, also keine Reihenfolgekonflikte und ein Name, der die Zugehörigkeit dokumentiert. Der Preis: ständig Namen erfinden und echte Duplizierung von Werten (dasselbe margin-top: 16px, in zwanzig Blöcken neu geschrieben).

CSS
.card {
  padding: 16px;
  border-radius: 8px;
}

.card__title {
  font-size: 1.25rem;
}

.card__title--muted {
  color: #6b7280;
}

.card--featured {
  border: 2px solid var(--brand);
}
BEM: flache Spezifität, explizite Zugehörigkeit

Der Utility-First-Ansatz (dessen dominante Ausprägung Tailwind ist) dreht die Logik um: keine Namen mehr, nur atomare Klassen mit einer einzigen Verantwortung, die im HTML zusammengesetzt werden. Die Vorteile sind messbar: kein Aufwand für die Benennung, Stile beim Markup angesiedelt (das Löschen der Komponente löscht ihre Stile) und ein finales CSS-Bundle, dessen Größe nahezu konstant bleibt, da die Utilities gemeinsam genutzt werden. Die Kompromisse ebenso: wortreiches HTML, die ins Markup verschobene Duplizierung, die eine Komponentenschicht (React, Vue, Partials) erfordert, um DRY zu bleiben, und eine Lernkurve für das Vokabular.

HTML
<article class="flex flex-col gap-4 rounded-lg
  border border-gray-200 p-4 shadow-sm">
  <h2 class="text-lg font-semibold">Invoice</h2>
  <p class="text-sm text-gray-600">
    Paid on March 12
  </p>
</article>
Utility-First: Die Stile leben im Markup

Diese Ansätze schließen sich nicht gegenseitig aus: Viele erfahrene Teams kombinieren sie - Utilities für Layout und Abstände, Komponentenklassen (BEM oder CSS Modules) für komplexe Muster und Zustände. Was die Dateiorganisation betrifft, bleibt das ITCSS-Prinzip die Referenz: Ordnung von generisch zu spezifisch (Reset, Basiselemente, Komponenten, Utilities). Die native @layer-Regel macht aus dieser Konvention eine Garantie auf Engine-Ebene: Die Priorität zwischen den Schichten ist unabhängig von der Spezifität der Selektoren, die sie enthalten.

CSS
@layer reset, base, components, utilities;

@layer base {
  h2 { font-size: 1.5rem; }
}

@layer components {
  #hero .btn { padding: 12px 24px; }
}

@layer utilities {
  .p-0 { padding: 0; }
}
Cascade Layers: Reihenfolge schlägt Spezifität

Wissenscheck

Stelle sicher, dass du die wichtigsten Punkte dieser Lektion behalten hast.

  1. Was bezeichnet in .card__title--muted das Segment --muted?
    • Eine CSS Custom Property
    • Einen Modifier: eine Variante des Elements card__title
    • Ein Kindelement von card__title
    • Einen von JavaScript verwalteten Zustand
  2. Was ist der wichtigste Beitrag von @layer zur Kaskade?
    • Sie erhöht die Spezifität der Selektoren der Schicht
    • Sie lässt die Reihenfolge der Schichten Vorrang vor der Spezifität der Selektoren haben
    • Sie isoliert die Stile einer Komponente, wie es ein Shadow DOM täte
    • Sie lädt die Schichten parallel, um das Rendering zu beschleunigen
  3. Welchen Kompromiss gehst du ein, wenn du einen Utility-First-Ansatz übernimmst?
    • Eine CSS-Datei, die proportional zur Anzahl der Seiten wächst
    • Eine hohe Spezifität, die schwer zu überschreiben ist
    • Wortreiches HTML, dessen Deduplizierung von einer Komponentenschicht abhängt