Abschnitt 16 · Lektion 1
Struktur und Namen
Ob du ein Stylesheet in einem Jahr noch verstehst, hängt an zwei Fragen. Wo gehört eine neue Regel hin? Und wenn zwei Regeln sich widersprechen, welche gewinnt und warum?
Beide Fragen haben eine Antwort, die nichts kostet. Man muss sie nur einmal am Anfang geben.
Die Reihenfolge einer Datei
Von oben nach unten stehen Reset, Tokens, Basis, Komponenten und Utilities.
In der Aufgabe sind es vier. Dort fehlt der Layer für die Tokens, weil die Datei noch keine Tokens hat. Sobald welche dazukommen, steht tokens zwischen reset und basis.
Der Reset räumt die Vorgaben des Browsers weg, mit denen man nicht arbeiten will. Die Tokens sind das System aus Lektion 5.5. Die Basis gibt Body, Überschriften und Links ihr Aussehen, ohne eine einzige Klasse. Die Komponenten sind Karte, Button, Formular. Und die Utilities sind die kleinen Helfer, die eine einzige Sache tun.
Diese Reihenfolge folgt der Kaskade von allgemein nach speziell. Das Spätere überschreibt das Frühere.
@layer legt die Reihenfolge fest
<article class="karte">
<h2 class="karte__titel zentriert">Mit Layern</h2>
<p class="karte__text">Die Utility gewinnt, obwohl sie schwächer ist.</p>
</article> /* Die Reihenfolge steht einmal oben und gilt,
egal wo die Regeln später landen. */
@layer reset, basis, komponenten, utilities;
@layer reset {
*,
*::before,
*::after {
box-sizing: border-box;
}
body,
h2,
p {
margin: 0;
}
}
@layer basis {
body {
padding: 24px;
font-family: system-ui, sans-serif;
line-height: 1.5;
}
}
@layer komponenten {
.karte {
padding: 24px;
border: 1px solid #d4d4d8;
border-radius: 12px;
}
/* Zwei Klassen, also stärker als die Utility. */
.karte .karte__titel {
margin-bottom: 8px;
font-size: 20px;
text-align: left;
}
}
@layer utilities {
.zentriert {
text-align: center;
}
} Die bloße Reihenfolge in der Datei hält nur so lange, wie sich alle daran halten. @layer reset, basis, komponenten, utilities; schreibt sie einmal oben fest, und ab da ist es egal, wo eine Regel später landet.
Zwischen zwei Layern zählt die Spezifität gar nicht mehr. Eine Utility mit einer Klasse schlägt eine Komponentenregel mit zwei Klassen, einfach weil ihr Layer weiter hinten steht.
<article class="karte">
<h2 class="karte__titel zentriert">Ohne Layer</h2>
<p class="karte__text">Die Utility verliert und tut gar nichts.</p>
</article> *,
*::before,
*::after {
box-sizing: border-box;
}
body,
h2,
p {
margin: 0;
}
body {
padding: 24px;
font-family: system-ui, sans-serif;
line-height: 1.5;
}
.karte {
padding: 24px;
border: 1px solid #d4d4d8;
border-radius: 12px;
}
.karte .karte__titel {
margin-bottom: 8px;
font-size: 20px;
text-align: left;
}
/* Sie steht ganz unten und verliert trotzdem: Zwei
Klassen schlagen eine, und daran ändert die
Reihenfolge in der Datei nichts. */
.zentriert {
text-align: center;
} Die beiden Beispiele haben gleiches Markup, gleiche Regeln und gleiche Reihenfolge in der Datei. Ohne Layer gewinnt die Komponente, denn zwei Klassen sind mehr als eine. An diesem Punkt greift im Alltag jemand zu !important. Ab da wird es unangenehm.
Welche der beiden Rechnungen gerade läuft, steht im Reiter „Regeln“. An der Überschrift im ersten Beispiel steht ganz oben .zentriert mit 0-1-0 und dem Vermerk @layer utilities. Darunter steht die Komponentenregel .karte .karte__titel mit 0-2-0 und text-align überstimmt aus @layer utilities. Die schwächere Regel steht also über der stärkeren. Durchgestrichen ist nur die eine Zeile, und margin-bottom und font-size derselben Regel gelten weiter.
Im zweiten Beispiel siehst du dieselbe Liste andersherum. Oben .karte .karte__titel mit 0-2-0, darunter .zentriert mit überstimmt durch höhere Spezifität (0-2-0). Zwei Beispiele, ein Unterschied, und im Vermerk steht er beim Namen.
Dazu kommt die eine Überraschung aus Abschnitt 3. Regeln ohne Layer stehen über allen Layern. Wenn ich mit Layern anfange, kommt deshalb alles in einen Layer, oder gar nichts.
Namen, die sich selbst erklären
BEM steht für Block, Element, Modifier. Die Namen sehen sperrig aus, aber sie lösen ein Problem. Du siehst an ihnen, wozu etwas gehört.
.karte ist der Block. .karte__titel mit zwei Unterstrichen ist ein Element, im Sinn von BEM also ein Teil des Blocks, der ohne ihn keinen Sinn ergibt. Mit einem HTML-Element hat das Wort hier nichts zu tun. .karte--gross mit zwei Bindestrichen ist ein Modifier, also eine Abwandlung des Blocks.
Was das bringt, merkst du beim Löschen. Wenn die Karte irgendwann verschwindet, findest du mit einer einzigen Suche nach karte alles im Stylesheet, was mit ihr zusammen verschwinden darf. Bei Namen wie .titel und .gross weiß das niemand. Also löscht sie auch niemand, und jede Datei wächst nur noch.
Zwei Dinge halte ich dabei ein. Ein BEM-Element bekommt kein eigenes Element angehängt, denn .karte__titel__text ist ein Zeichen dafür, dass da eine eigene Komponente steckt. Und der Modifier wiederholt den Blocknamen nicht, es heißt .karte--gross und nicht .karte--karte-gross.
Utilities und ihre Grenze
Eine Utility macht eine Sache, wie .zentriert, .versteckt oder .abstand-oben. Das ist praktisch, solange es zwanzig davon gibt.
Wer für jede Eigenschaft und jeden Wert eine Klasse anlegt, hat eine Bibliothek gebaut. Das ist ein legitimer Ansatz, nur nehme ich dann eine fertige, statt sie selbst zu schreiben. Der schlechte Mittelweg sind zwanzig Klassen an einem Element im HTML, die zusammen eine Komponente ergeben, und diese Komponente hat dann keinen Namen, unter dem man sie wiederfinden könnte.
Ein Reset in vier Entscheidungen
<img src="/lernen/media/arbeitsplatz-600.jpg" alt="Ein Schreibtisch vor einer dunkelgrünen Wand mit Notizbuch, Farn, Tasse und Laptop">
<h2>Überschrift</h2>
<p>Ein Absatz mit Text.</p>
<form>
<input type="text" value="Erbt die Schrift der Seite">
<button type="button">Button</button>
</form> /* Mehr braucht es 2026 nicht. */
*,
*::before,
*::after {
box-sizing: border-box;
}
body,
h1,
h2,
h3,
p,
figure,
blockquote {
margin: 0;
}
img,
video {
display: block;
max-width: 100%;
}
input,
button,
textarea,
select {
font: inherit;
}
body {
padding: 24px;
font-family: system-ui, sans-serif;
line-height: 1.5;
}
form {
display: flex;
gap: 8px;
margin-top: 16px;
} box-sizing: border-box global. Die Außenabstände der Textelemente auf null, damit man sie selbst setzt. display: block und max-width: 100% an Bildern, damit sie nicht auf der Grundlinie sitzen und nicht überlaufen. font: inherit an den Formularelementen, weil die ihre Schrift sonst vom Betriebssystem holen. Die line-height am Body im Beispiel gehört eher schon zur Basis.
Die großen Resets von früher haben Unterschiede zwischen den Browsern geradegebogen, die es heute nicht mehr gibt. Übrig bleiben diese vier Entscheidungen, und die treffe ich lieber selbst.
In der Aufgabe steht ein Stylesheet in vier Abschnitten, aber noch ohne einen einzigen Layer.
Zum Mitnehmen
Die Datei bekommt eine feste Reihenfolge der Layer, und @layer schreibt sie oben fest. Dazu kommen Namen, an denen man sieht, wozu eine Klasse gehört.
Jetzt du
Basis Konto, kostenlosZu dieser Lektion gehört eine Aufgabe. Du schreibst den Code selbst, und nach jedem Lauf sagt dir eine Prüfliste, was schon stimmt.
Dafür brauchst du das Basis Konto. Es kostet nichts, und ein Passwort gibt es auch nicht.
Was in dieser Lektion steckt
-
Artikel mit 3 Beispielen zum Ausprobieren
Steht hier, ohne Konto lesbar.
-
Aufgabe im Editor, direkt im Browser geprüft
Öffnet sich mit dem Basis Konto.