BEM 101

Avatar of Robin Rendle
Robin Rendle am

DigitalOcean bietet Cloud-Produkte für jede Phase Ihrer Reise. Starten Sie mit 200 $ kostenlosem Guthaben!

Der folgende Beitrag ist ein Gemeinschaftsprojekt von Gastautor Joe Richardson, Robin Rendle und vielen Mitarbeitern von CSS-Tricks. Joe wollte einen Beitrag über BEM schreiben, was uns gefiel, und fast jeder hier hatte Gedanken und Meinungen zu BEM, also dachten wir, wir tun uns alle zusammen und machen es gemeinsam.

Die Methodik Block, Element, Modifier (allgemein bekannt als BEM) ist eine beliebte Namenskonvention für Klassen in HTML und CSS. Entwickelt von dem Team bei Yandex, zielt sie darauf ab, Entwicklern zu helfen, die Beziehung zwischen HTML und CSS in einem bestimmten Projekt besser zu verstehen.

Hier ist ein Beispiel dafür, wie ein CSS-Entwickler im BEM-Stil schreiben könnte

/* Block component */
.btn {}

/* Element that depends upon the block */ 
.btn__price {}

/* Modifier that changes the style of the block */
.btn--orange {} 
.btn--big {}

In dieser CSS-Methodik ist ein Block eine Abstraktion auf oberster Ebene einer neuen Komponente, zum Beispiel eines Buttons: .btn { }. Dieser Block sollte als Elternteil betrachtet werden. Kindelemente, oder Elemente, können darin platziert werden und werden durch zwei Unterstriche nach dem Namen des Blocks gekennzeichnet, wie .btn__price { }. Schließlich können Modifier den Block manipulieren, sodass wir diese bestimmte Komponente thematisieren oder stylen können, ohne Änderungen an einem völlig unabhängigen Modul vorzunehmen. Dies geschieht durch Anhängen von zwei Bindestrichen an den Namen des Blocks, genau wie bei btn--orange.

Die Markup könnte dann so aussehen

<a class="btn btn--big btn--orange" href="https://css-tricks.de">
  <span class="btn__price">$9.99</span>
  <span class="btn__text">Subscribe</span>
</a>

Wenn ein anderer Entwickler dieses Markup schreiben würde und wir nicht mit dem CSS vertraut wären, sollten wir trotzdem eine gute Vorstellung davon haben, welche Klassen wofür verantwortlich sind und wie sie voneinander abhängen. Entwickler können dann ihre eigenen Komponenten erstellen und den bestehenden Block nach Herzenslust modifizieren. Ohne viel CSS zu schreiben, können Entwickler potenziell viele verschiedene Kombinationen von Buttons erstellen, indem sie einfach eine Klasse im Markup ändern

Siehe den Pen BEM Beispiel von CSS-Tricks (@css-tricks) auf CodePen.

Zuerst mag diese Syntax langsamer erscheinen, als einfach eine neue Klasse für jeden Button-Typ zu erstellen, aber das ist aus mehreren Gründen, die wir behandeln werden, nicht der Fall.

Warum sollten wir BEM in Betracht ziehen?

  1. Wenn wir eine neue Stilart einer Komponente erstellen wollen, können wir leicht sehen, welche Modifier und Elemente bereits existieren. Wir könnten sogar feststellen, dass wir gar kein CSS schreiben müssen, weil ein bereits vorhandener Modifier das tut, was wir brauchen.
  2. Wenn wir das Markup und nicht das CSS lesen, sollten wir schnell eine Vorstellung davon bekommen können, welches Element von einem anderen abhängt (im vorherigen Beispiel können wir sehen, dass .btn__price von .btn abhängt, auch wenn wir noch nicht wissen, was das tut).
  3. Designer und Entwickler können Komponenten konsistent benennen, um die Kommunikation zwischen Teammitgliedern zu erleichtern. Mit anderen Worten, BEM gibt jedem im Projekt eine deklarative Syntax, die sie teilen können, sodass sie auf derselben Wellenlänge sind.

Harry Roberts identifizierte einen weiteren wichtigen Vorteil der Verwendung einer Syntax wie BEM, wenn er über die Verbesserung des Vertrauens von Entwicklern schreibt

Das ist der Hauptgrund, warum wir mit überladenen Codebasen voller Legacy- und unbekanntem CSS enden, das wir uns nicht zu berühren trauen. Uns fehlt das Vertrauen, mit bestehenden Stilen arbeiten und diese modifizieren zu können, weil wir die Folgen der global agierenden und undichten Natur von CSS fürchten. Fast alle Probleme mit CSS in großem Maßstab laufen auf Vertrauen (oder dessen Fehlen) hinaus: Die Leute wissen nicht mehr, was Dinge tun. Die Leute trauen sich nicht, Änderungen vorzunehmen, weil sie nicht wissen, wie weitreichend die Auswirkungen sein werden.

Ebenso argumentiert Philip Walton, dass dieses Problem gelöst werden kann, wenn genügend Entwickler sich an die Prinzipien von BEM halten

Während 100% vorhersagbarer Code vielleicht nie möglich sein wird, ist es wichtig, die Kompromisse zu verstehen, die man mit den gewählten Konventionen eingeht. Wenn Sie sich strikt an die BEM-Konventionen halten, können Sie Ihren CSS in Zukunft mit vollem Vertrauen aktualisieren und ergänzen, dass Ihre Änderungen keine Nebenwirkungen haben werden.

Wenn Entwickler also zuversichtlicher an einem Projekt arbeiten können, werden sie sicher klügere Entscheidungen darüber treffen, wie diese visuellen Komponenten verwendet werden sollten. Diese Methodik ist vielleicht keine perfekte Lösung für all diese Leiden, aber sie gibt den Entwicklern sicherlich einen Standard an die Hand, um zukünftig besseren, besser wartbaren Code zu schreiben.

Ein weiterer kluger Teil von BEM ist, dass alles eine Klasse ist und nichts verschachtelt ist. Das macht die CSS-Spezifität sehr flach und niedrig, was eine gute Idee ist. Es bedeutet, dass Sie sich nicht über Spezifität streiten müssen.

Werfen wir einen Blick auf einige der Probleme mit BEM...

Probleme mit BEM CSS

Natürlich wird niemand Sie zwingen, wenn Sie von den BEM-Regeln abweichen. Sie könnten immer noch einen CSS-Selektor schreiben wie diesen

.nav .nav__listItem .btn--orange {
  background-color: green;
}

Das sieht so aus, als hätte es Teile von BEM, aber es ist kein BEM. Es hat verschachtelte Selektoren, und der Modifikator beschreibt nicht einmal genau, was passiert. Wenn wir das tun würden, würden wir die Spezifitätsflachheit, die bei BEM so hilfreich ist, durcheinander bringen.

Ein Block (wie z. B. .nav) sollte niemals die Stile eines anderen Blocks oder Modifikators (wie z. B. .btn--orange) überschreiben. Andernfalls wäre es fast unmöglich, das HTML zu lesen und zu verstehen, was diese Komponente tut; dabei werden wir das Vertrauen eines anderen Entwicklers in die Codebasis erheblich erschüttern. Das gilt auch für HTML: Was würden Sie erwarten, wenn Sie das folgende Markup sehen?

<a class="btn" href="https://css-tricks.de">
  <div class="nav__listItem">Item one</div>
  <div class="nav__listItem">Item two</div>
</a>

Was hier wahrscheinlich passiert ist, ist, dass ein Element in einem völlig unabhängigen Block den Code hat, den ein Entwickler benötigt, aber die Kindelemente keine .nav-Klasse als Elternteil benötigen. Das führt zu einer extrem verwirrenden und inkonsistenten Codebasis, die unter allen Umständen vermieden werden sollte. Wir können diese Probleme also zusammenfassen durch

  1. Niemals Modifier in einem unabhängigen Block überschreiben.
  2. Vermeiden Sie unnötige Elternelemente, wenn das Kind recht problemlos für sich allein existieren kann.

Weitere Beispiele für BEM in Aktion

Akkordeon-Demo

Siehe den Pen BEM Akkordeon von CSS-Tricks (@css-tricks) auf CodePen.

In diesem Beispiel gibt es einen Block, zwei Elemente und einen Modifier. Hier haben wir einen Modifier .accordion__copy–open erstellt, der uns wissen lässt, dass wir ihn nicht auf einem anderen Block oder Element verwenden sollten.

Navigation Demo

Siehe den Pen BEM Menu von CSS-Tricks (@css-tricks) auf CodePen.

Diese Navigationsdemo hat 1 Block, 6 Elemente und 1 Modifier. Es ist sogar völlig in Ordnung, Blöcke ohne Modifier zu erstellen. Irgendwann in der Zukunft kann ein Entwickler immer noch neue Modifier hinzufügen (oder anbinden), solange der Block konsistent bleibt.

Abneigungen gegen BEM

Vielleicht mögen Sie die doppelte Unterstrich- oder doppelte Bindestrich-Sache nicht. Gut, verwenden Sie etwas anderes Einzigartiges, das Sie konsequent durchsetzen werden.

Hier ist eine weitere Stimmung

Diese letzten drei Selektoren haben alle unterschiedliche Spezifitätsstufen. Sie erfordern entweder Eltern oder nicht. Ohne jegliche Regeln sagen sie nicht so viel aus wie die oben.

Ist es möglich, dass dieses winzige, isolierte Beispiel für Sie perfekt in Ordnung ist und Sie nie in Schwierigkeiten geraten? Vielleicht. Aber je mehr CSS Sie in einem Projekt haben, desto mehr summieren sich solche kleinen Dinge, desto mehr Spezifitäts- und Komplexitätskämpfe durchleben Sie.

Nicht um Samuel hier zu kritisieren, aber seine Stimmungen werden von vielen Leuten geteilt, daher ist es ein gutes Beispiel. Sie sehen BEM und lehnen es einfach rundweg ab. Wenn Sie BEM nicht mögen, ist das absolut in Ordnung, aber ich denke, es wäre schwer zu argumentieren, dass ein Regelwerk, das das Verständnis fördert und die Wartbarkeit von CSS unterstützt, eine schlechte Idee ist.

In der SMACSS-Methodik finden Sie wahrscheinlich einen CSS-Klassennamen mit drei Buchstaben. Modifier folgen dann dem Modulnamen mit einem Bindestrich

/* Example Module */
.btn { }

/* Modifier of the btn class */
.btn-primary { }

/* Btn Module with State */
.btn.is-collapsed { }

Das ist nur ein anderer Ansatz für dasselbe Problem. Es ist ziemlich ähnlich, aber Sie sind spezifischer bezüglich Abhängigkeiten und halten die Spezifität flach.

In OOCSS sind Blöcke ähnlich generisch.

/* Example Module */
.mod { }

/* Part of Module */
.inner { }

/* Talk Module */
.talk { }

/* Variation of part inside Module */
.talk .inner { }

Sie würden also mehrere Klassen im HTML für Variationen verwenden. Der Innenteil ist nicht so benannt, dass er eine Abhängigkeit hat, also ist es weniger klar, aber potenziell wiederverwendbarer. BEM würde .mod__inner und .mod--talk und .mod--talk__inner verwenden.

Das sind nur Variationen einer Methodik. Denken Sie daran, dass niemand Sie zwingt, dies sind selbst auferlegte Regeln, deren Wert aus deren Befolgung entsteht.

Sass und BEM

Für diejenigen unter Ihnen, die Sass schreiben und Verschachtelung zur Geltung von Stilen mögen, können Sie immer noch in einem verschachtelten Format erstellen, aber CSS erhalten, das nicht verschachtelt ist, mit @at-root

.block {
  @at-root #{&}__element {
  }
  @at-root #{&}--modifier {
  }
}

Ergibt

.block {
}
.block__element {
}
.block--modifier {
}

Und Sie können so abstrakt werden, wie Sie möchten! Schauen Sie sich Daniel Guillans BEM Constructor oder Anders Schmidt Hansens Expressive BEM an.

Zusammenfassung

Zusammenfassend lässt sich sagen, dass BEM zwar nicht alle unsere Probleme lösen wird, aber außerordentlich nützlich für die Erstellung skalierbarer und wartbarer Schnittstellen ist, bei denen jeder im Team eine klare Vorstellung davon haben sollte, wie Dinge verbessert werden können. Das liegt daran, dass ein Großteil der Frontend-Entwicklung nicht nur um die netten Tricks geht, die kurzfristig ein kleines Problem lösen; wir brauchen Vereinbarungen, Versprechen und bindende soziale Verträge zwischen Entwicklern, damit sich unsere Codebasis im Laufe der Zeit anpassen kann.

Im Allgemeinen betrachte ich BEM als Antwort auf Nicolas Gallaghers Frage

Weitere Lektüre