CSS BEM #FTW

Warum die Verwendung von BEM für CSS eine gute Idee ist

2015 habe ich bereits einen Blogbeitrag über die Verwendung der Block Element Modifier-Technik geschrieben. Kurz zusammengefasst ging es damals um Folgendes.

…Ich habe sofort gesehen, dass das Konzept auf schwachen Code-Prinzipien basiert, nicht auf Einfachheit und Wiederverwendbarkeit…..

Vier Jahre und zahlreiche Projekte später, sehe ich aus meiner Website-Statistik, dass ein Widerruf ansteht. Ich sollte aber erläutern, dass ich meine damalige Meinung nicht zurückrufe, sondern, dass ich die Anwendung von BEM als Konzept viel hilfreicher gefunden habe, seitdem ich mit Nico und Joel an Projekten arbeite. Insbesondere wurde die Idee besser verständlich, als ich anfangs Jahr wieder anfing, ohne vordefinierte CSS-Frameworks zu programmieren.

Mein ursprünglicher Punkt steht – dass, wenn man die Zeit hat und wenn man nicht an einem eher kleinen Website arbeitet, die Verwendung semantischer CSS-Klassen für bestimmte Kombinationen von Elementen sinnvoll sein kann. Aber das ist heutzutage bei einem Programmierer selten der Fall. Websites sind viel komplexer als vor zehn oder sogar fünf Jahren, so dass etwas Struktur viel Ärger ersparen kann.

Durch die Anwendung von Scoping-Klassen auf Elementen und ihren konstituierenden Unterelementen können Konflikte schnell vermieden werden und durch die Verwendung dieser Technik schreibt man schlussendlich auch weniger CSS. Du wirst immer noch in Konflikt geraten, wenn du mit schlecht organisiertem CSS von Drittanbieter-Plugins konkurrierst… aber das ist ein anderes Problem. Durch die Arbeit mit dem Gutenberg-Editor in diesem Jahr habe ich mit meinen Kollegen die besonders schlanke CSS-Struktur für unsere Projekte weiterentwickelt. Wir müssen nicht mal überlegen, wo Definitionen zu finden sind. Die Struktur bei jedem Projekt ist glasklar und einfach zu verstehen.

Also, wie funktioniert CSS Scoping? Indem man dem äusseren HTML-Element einen Master-Klassennamen zuweist und Variationen dieses Master-Klassennamens zu den entsprechenden Unterelementen hinzufügt.

<article class="c-article">
    <header class="c-article__header">
        <h1 class="c-article__title">Article title</h1>
    </header>
    <div class="c-article__content">
        …
    </div>
</article>

Das generierte CSS für dieses Element könnte so aussehen. Keine Verschachtelung, keine Probleme durch die Spezifität von Descendant Selectors, und Regeln, die ausschliesslich auf einfachen Klassennamen basieren, unabhängig von der eigentlichen HTML-Struktur.

.c-article {
  border: 1px solid #eee;
  padding: 1rem;
  background-color: #f0f0f0;
}

.c-article__title {
  font-size: 2rem;
  margin: 0 0 1rem;
}

Was habe ich im Jahr 2015 falsch gemacht? Hier mein Preiselement aus dem Blogbeitrag als Beispiel.

<a class="btn" href="/prices/">
 <span class="btn__price">$9.99</span>
 <span class="btn__text">My product</span>
</a>

Ich beklagte mich darüber, dass wir vielleicht ein gemeinsames Styling auf alle Preiselemente anwenden wollen, indem ich sagte, dass das folgende CSS wahrscheinlich notwendig wäre.

.btn__price, .list__price, .header__price, .teaser__price {
 font-weight: bold;
 font-size: 110%;
}

Das stimmt aber nicht. Was ich damals übersehen habe, ist, dass ich mehrere Klassen zum gleichen Selektor hinzufügen kann. Durch die Verwendung eines identifizierenden Präfixes zum Klassennamen (o für Objekte, c für Komponenten) kann ich zwei Klassennamen kombinieren, um jedes Element semantisch zu beschreiben. Mein HTML sieht nun so aus:

<a class="o-button o-button--primary c-pricebutton" href="/prices/">
  <span class="o-button__price">$9.99</span>
  <span class="o-button__text">My product</span>
</a>

In diesem Fall kann ich die Styles wie folgend im SCSS definieren. Wie du sehen kannst, haben die Regeln für eine einfache Gestaltung der Buttons mit einem o-button–primary-Modifier versehen, um die Farbstile zu verändern. Die grössere Grösse und der fett gedruckte Schriftstil ergeben sich aus dem Klassennamen c-pricebutton.

.c-pricebutton {
 font-weight: bold;
 font-size: 110%;
}

.o-button {
 display: inline-block;
 padding: .25em;
 color: blue;
 background-color: white;
 &--primary {
  color: white;
  background-color: blue;
 }
}

In diesem Beispiel könnte man die gleiche Änderung möglicherweise mit einem o-button–large-Modifier anstatt c-pricebutton. Meiner Meinung nach, wäre eine semantische Definition dadurch entfernt, was unangebracht ist. Large hat keine semantische Bedeutung und wäre genau so inkorrekt wie eine Farbgebung wie red oder green. Definitionen für das Aussehen eines Elements gehören ins CSS: darum heisst die Technik ja Cascading Style Sheets.

Schlussendlich geht es um eine klare Aufgabenteilung: die Styling-Regeln gehören ins CSS und rein semantische Elemente mit semantischen Elementklassen werden im HTML verwendet.

WordCamp Zürich – Preview Nächster Post