BEM für Späteinsteiger

Es gibt bei uns eine gewisse Tradition, sich erst recht spät mit dem ganzen heißen Scheiß aus der WebDev-Hipster-Toolchain zu beschäftigen. Nachdem ich 2013 den staunenden Kollegen im Working-Draft-Podcast noch berichtete, dass wir außer jQuery quasi keine nennenswerten Frontend-Tools oder -Techniken verwenden, gab es in den letzten drei Jahren schon noch die eine oder andere Aufrüstungsmaßnahme in unserem Workflow. Aber es ist uns eben wichtig, nicht zuviel Energie in Lösungen zu stecken, die sich mittelfristig als Sackgasse erweisen. Gut abgehangene Technik schlägt jeden Hype.

Im Falle von BEM war es insbesondere die unfassbar schlechte Didaktik, mit der das System allerorts beworben wurde. Ich konnte schlicht keinen vernünftigen Fachartikel finden, der mich wirklich von den Vorzügen überzeugen konnte. Mit den nachfolgenden Zeilen kann ich diesen Zustand hoffentlich ein wenig verbessern!

Kurzer Hinweis

Ich werde hier aus Gründen auf die Bezeichnung „Element“ verzichten, wenn damit die nackten HTML-Strukturelemente wie <h1>Headline</h1> oder <img src="" alt="" /> gemeint sind. Ich nenne sie stattdessen Bausteine, um sie von den BEM-Elementen zu unterscheiden.

Das Problem

CSS ist zwar auf den ersten Blick kein sonderlich komplexes Styling-System, doch der Schein trügt: Jeder, der ein Projekt mit mehr als 2000 Zeilen CSS-Code gebaut hat oder gar vererbt bekommt, hat sich sicherlich schon darüber geärgert, dass es in CSS keine eingebaute, verpflichtende Systematik oder Architektur gibt, mit der sich große Projekte mit vielen unterschiedlichen, aber natürlich visuell verwandten Elementen besser organisieren lässt. Das einzige, was man sich üblicherweise zu Nutze macht, sind:

  • HTML: semantische, aber kurze Klassennamen, die irgendwie trotzdem das Styling erahnen lassen
  • HTML: multiple Klassen für unterschiedliche Stylings, die aus unterschiedlichen Kontexten geerbt werden können
  • CSS: lockere Gruppierung von irgendwie zusammengehörigen Selektoren
  • CSS: grobe Reihenfolge der Selektoren von allgemein zu speziell, von außen nach innen, und von oben nach unten
  • CSS: verschachtelte Selektoren mit zunehmender Spezifität – durch übersichtliche Einrückung in Präprozessoren verführerisch einfach!

Dies sind alles keine grundsätzlich schlechten Ideen, und die Fähigkeiten von CSS ermutigen uns ja auch, Dinge wie die Kaskade, die Hierarchie und die Spezifität auszunutzen. Jedoch stoßen viele der einstigen best practices schlichtweg an ihre Grenzen, wenn es um mehr gehen soll als nur das neue Blogdesign oder den One-Pager für den Friseurladen nebenan. Ganz speziell sind es drei Dinge, die auch mir als wirklich erfahrenen CSS-Artisten immer wieder Schwierigkeiten bereiten:

  1. Konsistentes Namenskonzept für Klassen
  2. Wiederverwendbarkeit von Styling-Regeln (in funktionierend)
  3. Überschreiben von Selektoren mit bereits zu starker Spezifität

Und genau bei diesen drei Dingen kann BEM uns behilflich sein. Es lohnt sich also, dranzubleiben!

Die Grundprinzipien

BEM ist eine freiwillige Konvention und eine Systematik, wie man Klassen in HTML vergibt und diese in CSS nutzt. Es ist eine Empfehlung und ein Vorschlag, aber kein festes Framework. Man könnte zwar theoretisch Software schreiben, die BEM irgendwie automatisch generiert, aber das ist alles Quatsch – wir nutzen BEM einfach als eine Möglichkeit, unseren CSS-Code gut zu organisieren, damit wir uns nicht mehr so oft an den Kopf greifen müssen.

Mit BEM vereinheitlichen und vereinfachen wir die Prinzipien von CSS noch stärker, so dass man von einer wirklich minimalistischen Struktur sprechen kann. Es wird auf so vieles verzichtet!

  • Alle(!) CSS-Selektoren bestehen aus lediglich je einer Klasse
  • Es gibt keine id-Selektoren (#header {}) und auch keine Baustein-Selektoren (h2 {})
  • Verschachtelungen jeglicher Art sind ebenfalls nicht erlaubt
  • Selbstredend ist auch !important kein Thema

Somit besitzt jeder Selektor die gleiche Spezifität und es entscheidet nunmehr ausschließlich die Reihenfolge im Quelltext, welche Regel greift. Peace of mind – die Spezifitätskriege sind vorbei!

Gleichzeitig hat dies aber zur Folge, dass jeder Baustein, welchen ich gezielt stylen möchte (also wirklich jeder!), mindestens eine Klasse erhalten muss, selbst wenn es sich um ein blödes a innerhalb eines li einer Navigation handelt. Das ist ganz schön hart! Es bläht den HTML-Code auf, macht ihn weniger gut lesbar und nimmt dem CSS-Code scheinbar seine Eleganz. Früher hätten wir beispielsweise so etwas geschrieben:

<ul class="navi">
    <li><a href="ueberuns.html">Über uns</a></li>
    <li><a href="vision.html">Vision</a></li>
    <li class="active"><a href="kontakt.html">Kontakt</a></li>
</ul>

ul.navi a {
    color: #090;
    text-decoration: none;
}

ul.navi .active > a {
    color: #000;
}

Mit BEM sieht das im Vergleich erstmal schlimm aus:

<ul class="navi">
    <li class="navi__item">
        <a class="navi__link" href="ueberuns.html">Über uns</a>
    </li>
    <li class="navi__item">
        <a class="navi__link"  href="vision.html">Vision</a>
    </li>
    <li class="navi__item navi__item--active">
        <a class="navi__link navi__link--active" href="kontakt.html">Kontakt</a>
    </li>
</ul>

.navi__link {
    color: #090;
    text-decoration: none;
}

.navi__link--active {
    color: #000;
}

Was stört uns intuitiv daran? Ich vermute, es ist zum einen die schiere Menge an langen, redundanten Klassen, und zum anderen die Klassennamen, die die Hierarchie des HTML-Konstruktes noch einmal doppeln. Warum nutzen wir nicht einfach die bereits vorhandene HTML-Hierarchie (ul als Container von li sowie li als Container von a) und machen damit sowohl das HTML als auch das CSS kürzer und eleganter?

Weil wir uns mit dieser „physischen“ Hierarchie jede Menge Ärger einhandeln, der am Anfang noch nicht als Ärger erkennbar ist, aber ab einer gewissen Projektgröße das Potenzial hat, den CSS-Code quasi unpflegbar zu machen. Auch wenn es ein Kernkonzept von CSS ist: Hierarchie auf Selektor-Ebene skaliert nicht. Deshalb verzichtet BEM darauf und bildet eine (vereinfachte) Hierarchie ausschließlich in den Klassennamen ab.

Die BEM-Klassennamen

Ich habe ganz bewusst darauf verzichtet, das Akronym BEM gleich am Anfang meines Textes zu erläutern, denn es verwirrt nur. (Genauso wie es keinen Sinn macht, die Cascade von CSS gleich am Anfang zu erläutern.) Doch nun ist der richtige Zeitpunkt gekommen! BEM steht für Block, Element und Modifier und beschreibt die Systematik, nach der die Klassennamen ausgedacht und vergeben werden. Keine große Sache.

Ein Block ist ein Container von grundsätzlich beliebiger Komplexität. Er enthält mehrere Elemente, die sinnvoll zum Block passen und diesen mit Leben füllen. Jeder Block und jedes Element kann außerdem einen optionalen Modifier haben, der das entsprechende Basis-Styling mit zusätzlichen CSS-Eigenschaften abwandelt und verfeinert, so dass es eben mehrere unterschiedliche Styling-Varianten dafür geben kann.

Die Schreibweise der BEM-Klassen ist zwar nicht platzsparend, aber einfach:

  • Blöcke haben ganz normale semantische Klassen: class="pagination"
  • darin enthaltene Elemente werden mit zwei Unterstrichen notiert: class="pagination__link"
  • Abwandlungen der Elemente erhalten, zusätzlich zur Originalklasse, eine mit Doppeltrennstrich ergänzte Variante: class="pagination__link pagination__link--active"
  • Aber auch Blöcke können direkt als Ganzes abgewandelt werden, insbesondere bei gewünschter Positionierung an anderer Stelle: class="pagination pagination--aside"

Übrigens: Styling-Varianten, die man im CSS über den Kontext eines im übergeordneten HTML-Bausteins realisiert, sind verboten, von daher kann es durchaus mal sein, dass man mehrere Elemente eines Blockes einzeln modifizieren muss, wie im oberen Beispiel mit dem --active-Modifier.

Übrigens 2: Natürlich zwingt euch niemand, absolut jeden Baustein mit einer Klasse zu versehen. Was ihr nicht stylen müsst, muss auch nicht verBEMt werden.

BEM als Parallel-„DOM“

Wichtig zu beachten ist, dass es im Verhältnis vom Block zu seinen Elementen nur eine einzige Hierarchie-Stufe gibt: alle Elemente eines Blocks sind – mit der BEM-Brille gesehen – auf einer Ebene, unabhängig davon, wie tief sie innerhalb des HTML tatsächlich verschachtelt sind. Somit bauen wir uns mit BEM im Grunde eine Parallel-Struktur auf, die sich auf zweierlei Arten vom HTML emanzipiert:

  1. Sie schafft eine eigene Hierarchie, die sich im Extremfall nur locker am vorhandenen HTML orientiert.
  2. Sie ist komplett „Tag-agnostisch“: Das Herumspielen mit h1- bis h6-Ebenen (SEO, anyone?) und das Anreichern mit HTML5-Semantik in Form von aside-, section- oder subhead-Tags hat keinerlei Auswirkungen auf das Styling. Ihr ahnt nicht, wie befreiend das ist!

Elemente, die gleichzeitig Blöcke sind

Ich schrieb oben, dass Blöcke eine grundsätzlich beliebige Hierarchie ausweisen können – und das stimmt auch. Denn wenn beispielsweise eine Gruppe von drei gleichartigen Teaserboxen nebeneinander dargestellt werden soll (für mobile natürlich untereinander), so habe ich ja zum einen das gesamte Teaserkonstrukt als Block, in dem die drei Teaser meine Elemente bilden. Zum anderen kann man sich aber auch jeden einzelnen Teaser als Block mit seinen unterschiedlichen Elementen wie Headline, Vorschaubild usw. vorstellen

Eine beispielhafte HTML-Struktur sähe nackt so aus:

<section>
    <article>
        <h3>Teaser 1</h3>
        <img src="" alt="" />
        <p>…</p>
    </article>
    <article>
        <h3>Teaser 2</h3>
        <img src="" alt="" />
        <p>…</p>
    </article>
    <article>
        <h3>Teaser 2</h3>
        <img src="" alt="" />
        <p>…</p>
    </article>
</section>

Unsere article-Bausteine könnten also Elemente der section sein, gleichzeitig aber als Blöcke für h3, img und p fungieren. Dies sähe in der Praxis dann so aus:

<section class="teasers">
    <article class="teasers__box box">
        <h3 class="box__headline">Teaser 1</h3>
        <img src="" alt="" class="box__image"  />
        <p class="box__intro">…</p>
    </article>
    <article class="teasers__box box box--highlight">
        <h3 class="box__headline">Teaser 2</h3>
        <img src="" alt="" class="box__image"  />
        <p class="box__intro">…</p>
    </article>
    <article class="teasers__box box">
        <h3 class="box__headline">Teaser 3</h3>
        <img src="" alt="" class="box__image"  />
        <p class="box__intro">…</p>
    </article>
</section>

Es hat sich als gute Konvention erwiesen, wenn der Name des untergeordneten Blocks identisch mit seinem Element-Anhängsel ist, in diesem Beispiel eben teasers__box und box. Somit macht man die Übergabe sichtbar. Es ist aber keine Pflicht.

Grundsätzlich lässt sich allerdings auch argumentieren, dass es hier keiner weiteren Block-Ebene bedarf. Man könnte auch den teasers-Block als Alleinherrscher walten lassen, etwa so:

<section class="teasers">
    <article class="teasers__box">
        <h3 class="teasers__headline">Teaser 1</h3>
        <img src="" alt="" class="teasers__image"  />
        <p class="teasers__intro">…</p>
    </article>
    <article class="teasers__box teasers__box--highlight">
        <h3 class="teasers__headline">Teaser 2</h3>
        <img src="" alt="" class="teasers__image"  />
        <p class="teasers__intro">…</p>
    </article>
    <article class="teasers__box">
        <h3 class="teasers__headline">Teaser 3</h3>
        <img src="" alt="" class="teasers__image"  />
        <p class="teasers__intro">…</p>
    </article>
</section>

Modularität auf Block-Ebene

Welches der obigen Beispiele euch besser gefällt, macht ihr am besten davon abhängig, wie komplex das Geschehen in den einzelnen Teasern sein soll, und ob man die Boxen auch evtl. einmal einzeln benötigt, ohne den teaser-Block drum herum.

Denn dies ist der Kern des Modularitäts-Versprechen von BEM: Wenn wir einen Baustein als Block ansehen, lässt er sich im HTML überallhin verpflanzen und sieht für sich genommen an jeder Stelle auch gleich aus. Sprechen wir hingegen den Baustein als untergeordnetes Element an, kann er von der Platzierung her mit ebenbürtigen Elementen interagieren – beispielsweise eine horizontale Reihe bilden, oder als Flexbox-Item noch viel interessanter im Kontext positioniert werden.

Ich nenne dies die duale Natur von BEM-Bausteinen: Sie können gleichzeitig Welle und Teilchen Block und Element sein. Oder, als CSS-Code formuliert:

.box { border: 1px solid #000; background: #ccc; }
.box--highlight { background: yellow; }
.teasers { display: table; }
.teasers__box { display: table-cell; }

BEM und Sass

Die unhandlichen Klassennamen von BEM-Projekten sind natürlich nicht nur im HTML ein visuelles Problem, sondern auch in handgeschriebenem CSS. Wer fuhrwerkt schon gerne in Code herum, der so aussieht:

.newsteaser {
    border: 1px solid #000;
    background: #ccc;
    padding: 1em;
}

.teasergroup {
    width: 80%;
    overflow: hidden;
}

.teasergroup__headline {
    font-size: 1.5em;
}

.teasergroup__newsteaser {
    float: left;
    width: 33%;
}

.teasergroup__newsteaser--emphasized {
    border-color: red;
}

Da viele von euch für das Schreiben von CSS sowieso einen Präprozessor verwenden, kann man beispielseise mit Sass die BEM-Hierarchie auch mit den entsprechenden Einrückungen abbilden:

.newsteaser {
    border: 1px solid #000;
    background: #ccc;
    padding: 1em;
}

.teasergroup {
    width: 80%;
    overflow: hidden;
    &__headline {
        font-size: 1.5em;
    }
    &__newsteaser {
        float: left;
        width: 33%;
        &--emphasized {
            border-color: red;
        }
    }
}

Wichtig dabei: Auch bei dieser scheinbar hierarchischen Verschachtelung verändert sich keineswegs die Spezifität der Selektoren. Alle Bausteine werden absolut gleichwertig angesprochen, lediglich die Reihenfolge entscheidet bei Konflikten, welche Regel gewinnt. Deshalb ist es auch sinnvolle Praxis, das für sich stehende Block-Styling eines dualen Bausteines zuerst zu behandeln, und erst im Anschluss daran die Platzierung und Anpassung im Kontext eine übergeordneten Blockes. Diese ist spezifischer und gehört von daher weiter nach hinten.

Fazit

Genau wie einige andere Ansätze (OOCSS oder SMACSS) versucht BEM, die negativen Erfahrungen, die jeder CSS-Entwickler in komplexen und sich agil entwickelnden Layouts unweigerlich macht, zu mindern. Dabei geht es nicht darum, eine Metasprache zu schaffen, wie es Sass tut. Sondern es geht darum, die vorhandenen Möglichkeiten von CSS sinnvoll zu nutzen sowie gefährliche Praktiken zu vermeiden.

CSS wurde, genau wie HTML, nicht von visuellen Designern erdacht, sondern von Informatikern. Trotzdem müssen wir heute Layouts damit umsetzen, die sehr wohl von Designern stammen. Manchmal sind es wir Designer selber, die mit CSS unsere Ideen umsetzen. Und die Projekte werden immer komplizierter, insbesondere in einem responsiven Web. Seien wir nicht traurig, dass wir superclever verschachtelte Child-Selektoren und mühsam erlernte Spezifitäten hinter uns lassen – sie haben sich einfach auf Dauer nicht bewährt und mehr Probleme aufgeworfen als gelöst.

Ich habe es selber ausprobiert und werde vorerst dabei bleiben; Ein Projekt mit BEM aufzubauen sorgt bei mir für gesunden Blutdruck und entspannte Gesichtszüge. Fast wie eine Wellness-Massage. Und das ist tatsächlich nur dezent übertrieben :-)

20 Kommentare

Dirk Schürjohann

Danke für den Artikel! Ein paar lose Anmerkungen:

Ich persönlich würde von der BEM-Notation in Sass absehen und die Selektoren ausschreiben. Damit sind sie nämlich einfacher zu finden, wenn man sie im HTML markiert und danach strunzdoof global im Projekt sucht. Zudem kann dich die IDE dabei unterstützen, indem sie Referenzen kennt — bin mir gerade nicht sicher, ob die gängigen IDEs das auch in Sass-Notation hinkriegen.

Das »Parallel-DOM« ist ein schöner Vergleich, finde ich. Macht es vielleicht einfacher, einen wesentlichen Vorteil von BEM zu verstehen, nämlich die lose Verbindung zur HTML-Struktur. Loose coupling statt tight coupling FTW!, das lernen wir doch alle seit Jahren.

Wir fahren ganz gut damit, BEM nicht immer so ganz eng zu sehen. Die Verwendung von Modifiern etwa: Laut reiner Lehre muss man sie an allen betroffenen Elementen verwenden, wenn man etwa verschiedene Stati einer Komponente durchspielt. Allerdings kann das recht müßig und aufwendig sein, so dass man durchaus auch mal auf das »alte« Schema zurückfallen möchte, nur einen Modifier für die gesamte Komponente zu verwenden und diesen dann durchzuvererben.
— Wenn man weiß, was man tut, kann das durchaus mal effizienter sein, ohne das Projekt zu beschmutzen. Ist dann nur kein reines BEM mehr.

Das wichtigste Feature von BEM abseits aller Namenskonventionsdinge ist aus meiner Sicht: Scope. Kein echter Scope natürlich, sondern eher ein Pseudo-Scope: Dein CSS vererbt sich nachwievor nach unten hin durch — weil CSS das nunmal so macht —, allerdings trifft es dabei auch bei verschachtelten Modulen niemals fremde Elemente, sondern allenfalls Elemente des gleichen Typs. Du vererbst also niemals fremd, und das ist es, was BEM so großartig macht.

Das anderthalbwichtigste Feature hast du bereits vollumfänglich beschrieben: BEM ermöglicht geringstmögliche CSS-Spezifität, und das ist die beste Voraussetzung für eine modulare Umgebung.

Vererbung und Spezifität sind (auf CSS bezogen) die beiden natürlichen Feinde einer modularen Umgebung.

Tom

danke. ich tue mich mit den dopplungen bei modifiern schwer: ```class=‘dings__ding dings__ding—active’```.
da sich dings__ding—active immer auf dings__ding bezieht, wäre es m.E. doch ausreichend, nur dings__ding—active zu vergeben und dieser class die eigenschaften von dings__ding zu vererben?
also
.dings__ding,
.dings__ding—active { display: inline-block;…}
.dings__ding—active { color: #900;…}

was ist der usecase für diese klassen dopplung bei modifiern im html?

Matthias Mees

„was ist der usecase für diese klassen dopplung bei modifiern im html“

Der Modifier ist ggf. ein Zustand, der per Javascript verändert wird – in dem Fall würde ein Entfernen des Modifiers alle Styles entfernen. Siehe auch diese GetBEM-FAQ

Nick

Dankeschön, sehr erhellend!

Bernhard H.

Ist BEM schon das Ende der Fahnenstange? Muss „skalierbares“ CSS immer mit komplett unleserlichem HTML zusammenkommen?

Ich habe mich von den Frontend-Profis belehren lassen und verwende auch BEM. Aber ich ärgere mich jedes mal, wenn ich so wahnsinnig viele, lange Klassennamen im HTML-Code herumschieben muss. Dagegen fallen die skalierbar-Probleme doch meistens eher gering aus? Am Ende beschäftigt man sich doch ohnehin deutlich länger mit irgendwelchen Browser-Eigenheiten und bastelt so lange herum, bis es irgendwie gut aussieht.

Kein Wunder, dass größere Projekte anfangen, ihre kompletten Styles in Javascript zu definieren.

Dirk Schürjohann

Bernhard, BEM ist sicherlich nicht das Ende der Fahnenstange, sondern war ein erster guter Ansatz, typische Probleme von CSS zu vermeiden. Die Idee wurde seitdem in diversen Varianten weitergetragen, und mit css-modules gibt es z. B. ein inzwischen sehr populäres »Automatik-BEM«. Dort werden Prefixe automatisch ergänzt, so dass du kurze Selektoren schreiben kannst, ohne Konflikte mit anderen Elementen zu produzieren. Allerdings macht sowas nur Sinn, wenn das zugehörige HTML generiert werden kann, denn natürlich müssen die automatisch generierten Klassen ebenso automatisch im HTML landen.

Wenn dein HTML stattdessen aus irgendeinem CMS purzelt oder statisch vorliegt, ohne dass noch irgendein Parser drüberlaufen möchte, bleibt man besser bei händischen Methoden, und da ist aus meiner Sicht BEM die vernünftigste.

Zu deiner Frage, warum das HTML unleserlich sein muss: Muss es gar nicht. Man kann die BEM-Methodik auch mit sehr kurzen Klassennamen umsetzen und statt `.progressive-list__list-item-link` sowas wie `.list__item-link` oder sogar `.list__link` schreiben. Wichtig ist nur, dass man jederzeit eindeutig bleibt. Aber ich finde, man muss nicht zu strikt an der Notation hängen, sondern kann durchaus auch etwas improvisieren. Immer unter der Prämisse, dass man weiß, was man tut, und dass es mit dem Team abgesprochen ist (falls es ein Team gibt).

Zu den von dir angesprochenen Skalierungs-Problemen vs. Browser-Inkonsistenzen: Ich bin der Meinung, dass modulare CSS-Entwicklung ohne BEM kaum möglich ist. Es funktioniert mit fähigen Menschen bis zu einem gewissen Grad, erfordert jedoch verhältnismäßig viel Energie (in Form von Abstimmung, Wissenstransfer, Testing, Korrekturen), Erfahrung und regelmäßige Anpassungen des Systems während der Entwicklungsphase. Böse gesagt: Es ist weder effizient noch robust. Mit BEM hingegen erstickst du ganz viele Fehlerquellen im Keim und kannst mit merklich weniger Aufwand viel mehr erreichen als ohne BEM.

Unserem kleinen Team hat noch nie etwas soviel Schub gegeben wie BEM (und vielleicht Laravel für PHP, aber das ist ein anderes Thema), deshalb diskutiere ich immer ziemlich verbissen, wenn es um BEM geht. Die Nachteile (Klassen im HTML) sind so dermaßen irrelevant im Vergleich zu den vielen Vorteilen, dass ich schlicht nicht mehr nachvollziehen kann, warum man kein BEM nutzen möchte/sollte.

(Disclaimer: Sobald Shadow DOM flächendeckend verfügbar ist, brauchen wir kein BEM mehr.)

Friedrich Lux

Auch von mir vielen Dank für diese überzeugende Einführung.

Gibt es von den erfahrenen BEMlern vielleicht noch einen Tipp zur großräumigeren CSS/SCSS Organisation/Dateiarchitektur? Thematisches Zusammenziehen in größeren Dateien oder eher exzessive Aufteilung in inkludierte Dateien.

Ändert sich hier was zu den gängigen Empfehlungen?
Sinnvolle Ansätze, Gerüste, Erfahrungen?

Danke im voraus…

Dirk Schürjohann

Friedrich, wenn man BEM mit Sass (o. ä.) nutzt, bietet sich an, jeden Block in einer separaten Datei zu erfassen. Das macht es übersichtlicher und unterstützt den Gedanken, in anderen Projekten wiederverwertet zu werden: Einer der wesentlichen Gründe, warum man modular entwickelt.

Je nach Größe und Komplexität der Website kommen dann durchaus einige Blöcke zusammen. Bei VDA sind es zum Beispiel 89. An dem Punkt wünscht man sich Globbing, also ein include mittels Wildcard * (was Sass nativ leider nicht unterstützt), um nicht 89 Includes manuell zu pflegen. Denn bei BEM ist die Reihenfolge der Styles ziemlich egal, es ist ja alles gekapselt und gleichermaßen (CSS-)unspezifisch, so dass man Blöcke problemlos automatisch includen kann. Jedenfalls: Globbing kann man anders lösen, muss man aber nicht.

Gunnar Bittersmann

Dirk Schürjohann schrieb: „BEM ermöglicht geringstmögliche CSS-Spezifität“

Das stimmt nicht. Geringstmögliche Spezifität hat der Universalselektor `*`; auch dessen Kombination wie der lobotomized owl selector `* + *`.

Als nächstes kommen Elementtypselektoren: `h1` hat geringere Spezifität als `.hauptüberschrift`. Und deren Kombination: `main h1` hat immer noch geringere Spezifität als `.hauptinhalt__überschrift`.

BEM ermöglicht nicht geringstmögliche, sondern gleiche Spezifität der Selektoren im Autorenstylesheet. Ob das nun gut ist oder Unsinn, ist nochmal eine andere Frage.

Weiterhin: „Sobald Shadow DOM flächendeckend verfügbar ist, brauchen wir kein BEM mehr.“

Das ist zu hoffen. Es ist aber zu befürchten, dass die Browserhersteller Web Components gegen die Wand fahren.

Dirk Schürjohann

Danke für die Korrektur, Gunnar. Ich muss mich offenbar mal genauer ausdrücken, wenn ich über Spezifität rede.

Mir geht es bei BEM immer um das Styling von Komponenten, nicht um die allgemeinen Basis-Styles einer Seite, die global spezifiziert werden, wie z. B. Schriften und Farben. Diese werden wie gewohnt über Elementtypselektoren abgefeiert und sind damit natürlich die unspezifischsten Selektoren im Stylesheet. Sobald es dann aber darum geht, die Inhaltselemente aufzubauen, kannst du den gewohnten Weg gehen:

.context h2
.context p
.context > ul > li
.context > ul a
.context > ul > li > ul > li > a

…oder eben den BEM-Weg:

.context
.context__headline
.context__paragraph
.context__list-item
.context__list-link
.context__list-link—special

Und hier ist BEM grundsätzlich der tendenziell (CSS-)unspezifischste Weg, weil alle Elemente über genau eine Klasse referenziert werden, und nicht mittels Elementtypselektoren, Attributselektoren oder sonstigen Kombinationen, die an einer Kontextklasse (hier: .context) hängen.

(Du kannst natürlich so kühn sein und deine Seite ausschließlich über Elementtypselektoren aufbauen, dann bleibst du unterhalb der BEM-Spezifität. Aber das wäre bestimmt nicht allzu praktikabel, weil du damit hochgradig an deine HTML-Struktur gebunden bist. Ändert sich die, zerfällt die Seite zu staub, und du wirst zurecht aus dem Projektteam gejagt.)

Hans Hansen

OMG, sowas würde ich mir niemals antun. Mir reicht

nav.main ul li a li a

Wenn sich dann die Struktur ändert muss ich ja nur die angaben im SCSS verschieben und fertig.

Dirk Schürjohann

Hans, das Problem ist nicht die Technik (Styles anpassen), sondern der Mensch: Er ist nicht geeignet für Spezifität und Vererbung. Wir können das nicht im Kopf, sondern müssen mit Hilfe von Werkzeugen prüfen, was wir tun. Wir sind deshalb ziemlich fehleranfällig und immer weniger effizient, je größer das Projekt wird.

Jetzt kann man argumentieren: Dann muss dieser Mensch halt besonders gut in HTML und CSS sein und sich zudem bemühen, alles richtig zu machen. Das reicht aber nicht. Denn zum einen hat man in größeren Projekten mit mehreren Menschen zu tun, die gemeinsam HTML und CSS schreiben, und zum anderen spielen unter Umständen diverse Kriterien mit rein, die dazu führen, dass sich die HTML-Struktur regelmäßig ändert. Sei es, weil das Projekt noch nicht vollständig definiert ist und immer wieder angepasst wird, oder aber auch schlicht deshalb, weil Komponenten das HTML dynamisch anpassen, um z. B. Inline-Editing zu ermöglichen, Datepicker zu injizieren oder sonstiges Zeug reinbringen. Weiß der Geier, es gibt immer Gründe.

Und selbst wenn man an dieser Stelle argumentiert: Scheiß drauf, das Team und ich sind so dermaßen gut darin, CSS immer wieder auf wechselnde Kontexte anzupassen — Warum zur Hölle sollte man sich sowas freiwillig antun?! — kommt das nächste Argument ins Spiel: Wiederverwertbarkeit. Natürlich willst du nicht in jedem neuen Projekt immer alles neu bauen und/oder an den jeweiligen Kontext anpassen müssen, sondern du möchtest Komponenten wieder verwerten. Du möchtest, dass sie möglichst autark funktionieren und im besten Fall sogar vollständig separat gepflegt werden können. Dass du vielleicht sogar fremde Komponenten reinholen kannst?

Um BEM zu verstehen, muss man mal kurz die Klassen ausblenden, an denen sich immer alle stören: Scheiß auf die Klassen. Danach wirst du merken, dass sich mit BEM deine Styles nicht mehr nach unten hin durch vererben, sondern am Element (gleichen Typs) kleben bleiben. Das wird dich aber erst dann so richtig flashen, sobald du zum ersten Mal Komponente-in-Komponente benutzt und merkst, dass es auf Anhieb funktioniert, weil keine von oben vererbten Styles im Weg sind. Von dem Punkt an wirst du vielleicht erkennen, dass Modularität ziemlich praktisch ist, und wirst hoffentlich zu dem Schluss kommen, dass es ohne die vielen BEM-Klassen (noch) nicht anders geht, falls man sich nicht fest an die HTML-Struktur binden möchte (siehe oben).

BEM ist der generische Weg, Nicht-BEM ist der manuelle Weg. Beides kann gut funktionieren, aber einer von beiden ist besser.

Christoph Zillgens

Ich habe BEM auch häufiger eingesetzt, bin aber früher oder später davon abgewichen, weil es gerade im Zusammenhang mit CMS nötig war, z.B. p und a ohne spezielle Klasse zu stylen.

Wie geht man mit solchen, vom Kunden übers CMS generierten HTML-Elementen um?

Gerrit

@Christoph: Ich gebe im Template dem umschließenden DIV-Container die Block-Klasse „usertext“ und mache dann an dieser Stelle im CSS tatsächlich eine kleine Ausnahme:

.usertext p { }
.usertext a { }
.usertext ol li { }

Geht nicht anders, aber diese Teil des CSS macht ja meist nur einen kleinen Bruchteil des Gesamt-CSS aus.

Dirk Schürjohann

Was Gerrit sagt. Nur nenne ich den Container .wysiwyg ;)

Hans Hansen

@Dirk Schürjohann: Danke erstmal für die Ausführliche Erläuterung – ABER

“Danach wirst du merken, dass sich mit BEM deine Styles nicht mehr nach unten hin durch vererben, sondern am Element (gleichen Typs) kleben bleiben.”

… das Vererben ist doch gerade ein Vorteil den man nutzen kann. “Cascading” halt – das ist ja gerade das Ding das das einem viel Arbeit abnimmt, ich möchte nicht für jedes Pups Element eine eigene Klasse definieren müssen. Irgendwie habe ich das Gefühl man versucht hier das “Cascading” aus CSS zu entfernen.

Hans Hansen

Ich hab z. B. hier ARTICLEs mit folgenden Klassen:

“col-level-a col-sm-6 col-lg-3 post-33 post type-post status-publish format-standard has-post-thumbnail hentry category-allgemein article_level_a”

Generiert vom CMS und alles andere als überflüssiger Krempel. Und da soll ich jetzt noch die Klassen der Eltern Elemente mit reinkleben? OMG :)

Gerrit

@Hans: Ja, wir verzichten größtenteils auf die Kaskade und die Spezifität, lies einfach den Artikel. Und wenn dein CMS solche Klassen ausspuckt, hast du es eventuell einfach nicht unter Kontrolle. Schon mal Kirby oder ProcessWire probiert?

Hans Hansen

@Gerrit: Habe schlicht kein Interesse daran diese Klassen zu entfernen, die sind sehr nützlich. Processwire ist sicher ein gutes System aber das geht auch alles mit Wordpress und ACF, also warum sich mit einem zusätzlichen CMS herumschlagen.

Hans Hansen

OT: Was spricht eigentlich dagegen die Klassennamen aufzuteilem mit underscores?

col-level-a _ _ _ border _ _ col-sm-6 col-lg-3

Element/Block _ _ _ Modifier _ _ Bootstrap Columns

Sieht doch gleich viel übersichtlicher aus.

Kommentar verfassen