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. Du fügst dem Block .card eine hervorgehobene Variante hinzu und hältst dich dabei strikt an die BEM-Konvention. Welchen Selektor schreibst du in die Lücke?
    .card {
      padding: 16px;
      border: 1px solid #e5e7eb;
    }
    
    ___ {
      border: 2px solid var(--brand);
    }
    • .card--featured
    • .card__featured
    • .card-featured
    • .card .featured
  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